From 8eb95d316f7b6fbad0ff798abfe7f70f89e812d2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 22 Apr 2018 00:00:00 +0200
Subject: Improved the way file formats are detected and loaded.

---
 plugins/dex/core.c                        |   55 +-
 plugins/dex/core.h                        |    3 +
 plugins/dex/format.c                      |  150 ++--
 plugins/dex/format.h                      |    5 +-
 plugins/dex/python/format.c               |   59 +-
 plugins/elf/core.c                        |   50 +-
 plugins/elf/core.h                        |    3 +
 plugins/elf/elf_def.h                     |    5 +
 plugins/elf/format.c                      |  129 ++-
 plugins/elf/format.h                      |    2 +-
 plugins/elf/python/format.c               |   58 +-
 plugins/pychrysalide/analysis/Makefile.am |    1 +
 plugins/pychrysalide/analysis/binary.c    |   91 +-
 plugins/pychrysalide/analysis/loaded.c    |   77 +-
 plugins/pychrysalide/analysis/loading.c   |  196 ++++
 plugins/pychrysalide/analysis/loading.h   |   56 ++
 plugins/pychrysalide/analysis/module.c    |    3 +
 plugins/pychrysalide/analysis/project.c   |   93 +-
 plugins/pychrysalide/core/Makefile.am     |    1 +
 plugins/pychrysalide/core/global.c        |  280 ++++++
 plugins/pychrysalide/core/global.h        |   42 +
 plugins/pychrysalide/core/module.c        |    2 +
 plugins/pychrysalide/format/executable.c  |    2 +-
 plugins/pychrysalide/plugin.c             |   66 +-
 src/analysis/binary.c                     |  511 ++++-------
 src/analysis/binary.h                     |   22 +-
 src/analysis/content-int.h                |    5 +
 src/analysis/content.c                    |   28 +
 src/analysis/content.h                    |    3 +
 src/analysis/contents/encapsulated.c      |   28 +
 src/analysis/contents/file.c              |   28 +
 src/analysis/contents/memory.c            |   28 +
 src/analysis/contents/restricted.c        |   28 +
 src/analysis/disass/disassembler.c        |  534 +++--------
 src/analysis/disass/disassembler.h        |   34 +-
 src/analysis/disass/fetch.c               |    2 +-
 src/analysis/loaded-int.h                 |   26 +
 src/analysis/loaded.c                     |  425 +++++++++
 src/analysis/loaded.h                     |   20 +
 src/analysis/loading.c                    | 1379 +++++++++++++++++++++++------
 src/analysis/loading.h                    |   96 +-
 src/analysis/project.c                    |  846 ++++++++++++++----
 src/analysis/project.h                    |   33 +-
 src/core/core.c                           |    8 +
 src/core/global.c                         |   98 +-
 src/core/global.h                         |   13 +
 src/format/format-int.h                   |   10 +
 src/format/format.c                       |   48 +
 src/format/format.h                       |    8 +-
 src/glibext/delayed-int.h                 |    8 +
 src/glibext/delayed.c                     |   90 +-
 src/glibext/delayed.h                     |    3 +
 src/gui/editem-int.h                      |    1 +
 src/gui/editor.c                          |   10 +-
 src/gui/menus/project.c                   |    6 +-
 src/main.c                                |    7 +-
 src/plugins/pglist.h                      |   14 +-
 src/plugins/plugin-def.h                  |   15 +-
 src/plugins/plugin-int.h                  |    6 +-
 src/plugins/plugin.c                      |   45 +
 src/plugins/plugin.h                      |    3 +-
 61 files changed, 4289 insertions(+), 1609 deletions(-)
 create mode 100644 plugins/pychrysalide/analysis/loading.c
 create mode 100644 plugins/pychrysalide/analysis/loading.h
 create mode 100644 plugins/pychrysalide/core/global.c
 create mode 100644 plugins/pychrysalide/core/global.h

diff --git a/plugins/dex/core.c b/plugins/dex/core.c
index 05130a6..869ef4b 100644
--- a/plugins/dex/core.c
+++ b/plugins/dex/core.c
@@ -24,7 +24,7 @@
 #include "core.h"
 
 
-#include <core/formats.h>
+#include <core/global.h>
 #include <plugins/plugin-def.h>
 
 
@@ -34,7 +34,7 @@
 
 
 DEFINE_CHRYSALIDE_PLUGIN("dex", "Add support for the DEX format", "0.1.0",
-                         RL("PyChrysalide", "dexbnf"), AL(PGA_PLUGIN_INIT));
+                         RL("PyChrysalide", "dexbnf"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
 
 
 
@@ -54,10 +54,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = register_format_matcher(dex_is_matching, NULL);
-
-    if (result)
-        result = register_format_loader("dex", "Dalvik Executable format", g_dex_format_new);
+    result = register_format_loader("dex", "Dalvik Executable format", g_dex_format_new);
 
     if (result)
         result = add_format_dex_module_to_python_module();
@@ -65,3 +62,49 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                gid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
+{
+    vmpa2t addr;                            /* Tête de lecture initiale    */
+    bool test;                              /* Bilan des accès mémoire     */
+    char magic[DEX_FILE_MAGIC_LEN];         /* Idenfiant standard          */
+    GExeFormat *format;                     /* Format DEX reconnu          */
+    GLoadedContent *loaded;                 /* Représentation chargée      */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+
+    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+    test = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic);
+
+    if (test)
+        test = (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0);
+
+    if (test)
+    {
+        format = g_dex_format_new(content);
+        loaded = g_loaded_binary_new(format);
+
+        resolver = get_current_content_resolver();
+        g_content_resolver_add_detected(resolver, gid, loaded);
+        g_object_unref(G_OBJECT(resolver));
+
+    }
+
+}
diff --git a/plugins/dex/core.h b/plugins/dex/core.h
index bc1a444..8a07f84 100644
--- a/plugins/dex/core.h
+++ b/plugins/dex/core.h
@@ -33,6 +33,9 @@
 /* Prend acte du chargement du greffon. */
 G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
 
+/* Procède à une opération liée à un contenu binaire. */
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, gid_t, GtkStatusStack *);
+
 
 
 #endif  /* _PLUGINS_DEX_CORE_H */
diff --git a/plugins/dex/format.c b/plugins/dex/format.c
index f4cfdc9..d3e18da 100755
--- a/plugins/dex/format.c
+++ b/plugins/dex/format.c
@@ -51,6 +51,12 @@ static void g_dex_format_dispose(GDexFormat *);
 /* Procède à la libération totale de la mémoire. */
 static void g_dex_format_finalize(GDexFormat *);
 
+/* Indique la désignation interne du format. */
+static const char *g_dex_format_get_name(const GDexFormat *);
+
+/* Assure l'interprétation d'un format en différé. */
+static bool g_dex_format_analyze(GDexFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Informe quant au boutisme utilisé. */
 static SourceEndian g_dex_format_get_endianness(const GDexFormat *);
 
@@ -83,52 +89,6 @@ static void g_dex_format_decompile(const GDexFormat *, void/*GCodeBuffer*/ *, co
 
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : content = contenu binaire à parcourir.                       *
-*                parent  = éventuel format exécutable déjà chargé.            *
-*                unused  = adresse non utilisée ici.                          *
-*                key     = identifiant de format trouvé ou NULL. [OUT]        *
-*                                                                             *
-*  Description : Indique si le format peut être pris en charge ici.           *
-*                                                                             *
-*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-FormatMatchStatus dex_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
-{
-    FormatMatchStatus result;               /* Bilan à renvoyer            */
-    vmpa2t addr;                            /* Tête de lecture initiale    */
-    bool status;                            /* Bilan des accès mémoire     */
-    char magic[DEX_FILE_MAGIC_LEN];         /* Idenfiant standard          */
-
-
-    /* REMME */
-    if (parent != NULL) return FMS_UNKNOWN;
-
-
-    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
-
-    status = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic);
-
-    status &= (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0);
-
-    if (status)
-    {
-        result = FMS_MATCHED;
-        *key = strdup(parent == NULL ? "dex" : "dexdbg");
-    }
-    else
-        result = FMS_UNKNOWN;
-
-    return result;
-
-}
-
-
 /* Indique le type défini pour un format d'exécutable DEX. */
 G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT);
 
@@ -158,6 +118,8 @@ static void g_dex_format_class_init(GDexFormatClass *klass)
 
     fmt = G_BIN_FORMAT_CLASS(klass);
 
+    fmt->get_name = (format_get_name_fc)g_dex_format_get_name;
+    fmt->analyze = (format_analyze_fc)g_dex_format_analyze;
     fmt->get_endian = (format_get_endian_fc)g_dex_format_get_endianness;
 
     exe = G_EXE_FORMAT_CLASS(klass);
@@ -240,8 +202,6 @@ static void g_dex_format_finalize(GDexFormat *format)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
-*                parent  = éventuel format exécutable déjà chargé.            *
-                 status  = barre de statut à tenir informée.                  *
 *                                                                             *
 *  Description : Prend en charge un nouveau format Dex.                       *
 *                                                                             *
@@ -251,54 +211,96 @@ static void g_dex_format_finalize(GDexFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)
+GExeFormat *g_dex_format_new(GBinContent *content)
 {
     GDexFormat *result;                     /* Structure à retourner       */
-    GBinFormat *base;                       /* Version basique du format   */
-    GExeFormat *exe_format;                 /* Autre version du format     */
-    vmpa2t pos;                             /* Position de tête de lecture */
-    wgroup_id_t gid;                        /* Identifiant pour les tâches */
 
     result = g_object_new(G_TYPE_DEX_FORMAT, NULL);
 
-    base = G_BIN_FORMAT(result);
-    exe_format = G_EXE_FORMAT(result);
+    g_binary_format_set_content(G_BIN_FORMAT(result), content);
 
-    g_binary_format_set_content(base, content);
+    return G_EXE_FORMAT(result);
 
-    init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
+}
 
-    if (!read_dex_header(result, &pos, &result->header))
-        goto gdfn_error;
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static const char *g_dex_format_get_name(const GDexFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
 
-    /* TODO : vérifier que les *_id ne se chevauchent pas */
+    result = "dex";
 
+    return result;
 
-    gid = g_work_queue_define_work_group(get_work_queue());
+}
 
-    if (!load_all_dex_types(result, gid, status))
-        goto gdfn_error;
 
-    if (!load_all_dex_fields(result, gid, status))
-        goto gdfn_error;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure l'interprétation d'un format en différé.              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    if (!load_all_dex_classes(result, gid, status))
-        goto gdfn_error;
+static bool g_dex_format_analyze(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinFormat *base;                       /* Version basique du format   */
+    GExeFormat *exe;                        /* Autre version du format     */
+    vmpa2t pos;                             /* Position de tête de lecture */
 
-    preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
+    result = false;
 
-    if (!g_executable_format_complete_loading(exe_format, status))
-        goto gdfn_error;
+    base = G_BIN_FORMAT(format);
+    exe = G_EXE_FORMAT(format);
 
-    return base;
+    init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
 
- gdfn_error:
+    if (!read_dex_header(format, &pos, &format->header))
+        goto gdfa_error;
 
-    g_object_unref(G_OBJECT(result));
 
-    return NULL;
+    /* TODO : vérifier que les *_id ne se chevauchent pas */
+
+
+    if (!load_all_dex_types(format, gid, status))
+        goto gdfa_error;
+
+    if (!load_all_dex_fields(format, gid, status))
+        goto gdfa_error;
+
+    if (!load_all_dex_classes(format, gid, status))
+        goto gdfa_error;
+
+    preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
+
+    if (!g_executable_format_complete_loading(exe, status))
+        goto gdfa_error;
+
+    result = true;
+
+ gdfa_error:
+
+    return result;
 
 }
 
diff --git a/plugins/dex/format.h b/plugins/dex/format.h
index 81a4b0f..6850ed1 100755
--- a/plugins/dex/format.h
+++ b/plugins/dex/format.h
@@ -52,14 +52,11 @@ typedef struct _GDexFormat GDexFormat;
 typedef struct _GDexFormatClass GDexFormatClass;
 
 
-/* Indique si le format peut être pris en charge ici. */
-FormatMatchStatus dex_is_matching(GBinContent *, GExeFormat *, void *, char **);
-
 /* Indique le type défini pour un format d'exécutable DEX. */
 GType g_dex_format_get_type(void);
 
 /* Prend en charge un nouveau format DEX. */
-GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *, GtkStatusStack *);
+GExeFormat *g_dex_format_new(GBinContent *);
 
 /* Présente l'en-tête DEX du format chargé. */
 const dex_header *g_dex_format_get_header(const GDexFormat *);
diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c
index a406f62..a421549 100644
--- a/plugins/dex/python/format.c
+++ b/plugins/dex/python/format.c
@@ -25,6 +25,7 @@
 #include "format.h"
 
 
+#include <assert.h>
 #include <pygobject.h>
 
 
@@ -69,67 +70,17 @@ static PyObject *py_dex_format_new(PyTypeObject *type, PyObject *args, PyObject
 {
     PyObject *result;                       /* Instance à retourner        */
     PyObject *content_obj;                  /* Objet pour le contenu       */
-    PyObject *parent_obj;                   /* Objet pour le parent        */
-    PyObject *status_obj;                   /* Objet pour la progression   */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Instance GLib du contenu    */
-    GExeFormat *parent;                     /* Instance GLib du parent     */
-    GtkStatusStack *status;                 /* Instance GTK de suivi       */
-    GBinFormat *format;                     /* Création GLib à transmettre */
+    GExeFormat *format;                     /* Création GLib à transmettre */
 
-    parent_obj = Py_None;
-    status_obj = Py_None;
-
-    ret = PyArg_ParseTuple(args, "O|OO", &content_obj, &parent_obj, &status_obj);
+    ret = PyArg_ParseTuple(args, "O!", get_python_binary_content_type(), &content_obj);
     if (!ret) return NULL;
 
-    ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type());
-    if (!ret)
-    {
-        PyErr_SetString(PyExc_TypeError, _("The first argument must be an instance of BinContent."));
-        return NULL;
-    }
-
     content = G_BIN_CONTENT(pygobject_get(content_obj));
 
-    if (parent_obj == Py_None)
-        parent = NULL;
-
-    else
-    {
-        ret = PyObject_IsInstance(parent_obj, (PyObject *)get_python_executable_format_type());
-        if (!ret)
-        {
-            PyErr_SetString(PyExc_TypeError, _("The second argument must be a container format or None."));
-            return NULL;
-        }
-
-        parent = G_EXE_FORMAT(pygobject_get(parent_obj));
-
-    }
-
-    if (status_obj == Py_None)
-        status = NULL;
-
-    else
-    {
-        ret = PyObject_IsInstance(status_obj, (PyObject *)get_python_binary_content_type());
-        if (!ret)
-        {
-            PyErr_SetString(PyExc_TypeError, _("The third argument must be a status bar object or None."));
-            return NULL;
-        }
-
-        status = GTK_STATUS_STACK(pygobject_get(status_obj));
-
-    }
-
-    format = g_dex_format_new(content, parent, status);
-    if (format == NULL)
-    {
-        PyErr_SetString(PyExc_RuntimeError, _("Unable to load the DEX format."));
-        return NULL;
-    }
+    format = g_dex_format_new(content);
+    assert(format != NULL);
 
     result = pygobject_new(G_OBJECT(format));
 
diff --git a/plugins/elf/core.c b/plugins/elf/core.c
index 0cfd49c..7486242 100644
--- a/plugins/elf/core.c
+++ b/plugins/elf/core.c
@@ -24,7 +24,7 @@
 #include "core.h"
 
 
-#include <core/formats.h>
+#include <core/global.h>
 #include <plugins/plugin-def.h>
 
 
@@ -34,7 +34,7 @@
 
 
 DEFINE_CHRYSALIDE_PLUGIN("elf", "Add support for the ELF format", "0.1.0",
-                         RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
+                         RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
 
 
 
@@ -65,3 +65,49 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                gid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
+{
+    vmpa2t addr;                            /* Tête de lecture initiale    */
+    bool test;                              /* Bilan des accès mémoire     */
+    char magic[SELFMAG];                    /* Idenfiant standard          */
+    GExeFormat *format;                     /* Format ELF reconnu          */
+    GLoadedContent *loaded;                 /* Représentation chargée      */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+
+    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+    test = g_binary_content_read_raw(content, &addr, SELFMAG, (bin_t *)magic);
+
+    if (test)
+        test = (memcmp(magic, ELFMAG, SELFMAG) == 0);
+
+    if (test)
+    {
+        format = g_elf_format_new(content);
+        loaded = g_loaded_binary_new(format);
+
+        resolver = get_current_content_resolver();
+        g_content_resolver_add_detected(resolver, gid, loaded);
+        g_object_unref(G_OBJECT(resolver));
+
+    }
+
+}
diff --git a/plugins/elf/core.h b/plugins/elf/core.h
index 52ded90..ec9ed5c 100644
--- a/plugins/elf/core.h
+++ b/plugins/elf/core.h
@@ -33,6 +33,9 @@
 /* Prend acte du chargement du greffon. */
 G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
 
+/* Procède à une opération liée à un contenu binaire. */
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, gid_t, GtkStatusStack *);
+
 
 
 #endif  /* _PLUGINS_ELF_CORE_H */
diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h
index bb33d6d..a820eac 100644
--- a/plugins/elf/elf_def.h
+++ b/plugins/elf/elf_def.h
@@ -111,6 +111,11 @@ typedef union _elf_header
 #define EI_ABIVERSION   8                   /* Version de l'ABI            */
 #define EI_PAD          9                   /* Premier octet de bourrage   */
 
+/* ... EI_MAG* */
+
+#define ELFMAG          "\x7f\x45\x4c\x46"  /* .ELF                         */
+#define SELFMAG         4
+
 /* ... EI_CLASS */
 
 #define ELFCLASSNONE    0                   /* Objet invalide              */
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index eb22059..0fb2d1e 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -60,6 +60,12 @@ static void g_elf_format_dispose(GElfFormat *);
 /* Procède à la libération totale de la mémoire. */
 static void g_elf_format_finalize(GElfFormat *);
 
+/* Indique la désignation interne du format. */
+static const char *g_elf_format_get_name(const GElfFormat *);
+
+/* Assure l'interprétation d'un format en différé. */
+static bool g_elf_format_analyze(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Informe quant au boutisme utilisé. */
 static SourceEndian g_elf_format_get_endianness(const GElfFormat *);
 
@@ -159,6 +165,8 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
 
     fmt = G_BIN_FORMAT_CLASS(klass);
 
+    fmt->get_name = (format_get_name_fc)g_elf_format_get_name;
+    fmt->analyze = (format_analyze_fc)g_elf_format_analyze;
     fmt->get_endian = (format_get_endian_fc)g_elf_format_get_endianness;
 
     fmt->complete = (format_complete_analysis_fc)g_elf_format_complete_analysis;
@@ -236,8 +244,6 @@ static void g_elf_format_finalize(GElfFormat *format)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
-*                parent  = éventuel format exécutable déjà chargé.            *
-                 status  = barre de statut à tenir informée.                  *
 *                                                                             *
 *  Description : Prend en charge un nouveau format ELF.                       *
 *                                                                             *
@@ -247,65 +253,113 @@ static void g_elf_format_finalize(GElfFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)
+GExeFormat *g_elf_format_new(GBinContent *content)
 {
     GElfFormat *result;                     /* Structure à retourner       */
-    GBinFormat *base;                       /* Version basique du format   */
-    GExeFormat *exe_format;                 /* Autre version du format     */
 
     result = g_object_new(G_TYPE_ELF_FORMAT, NULL);
 
-    base = G_BIN_FORMAT(result);
-    exe_format = G_EXE_FORMAT(result);
+    g_binary_format_set_content(G_BIN_FORMAT(result), content);
+
+    return G_EXE_FORMAT(result);
 
-    g_binary_format_set_content(base, content);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_elf_format_get_name(const GElfFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = "elf";
+
+    return result;
+
+}
 
-    if (!read_elf_header(result, &result->header, &result->is_32b, &result->endian))
-        goto gefn_error;
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure l'interprétation d'un format en différé.              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinFormat *base;                       /* Version basique du format   */
+    GExeFormat *exe;                        /* Autre version du format     */
+
+    result = false;
+
+    base = G_BIN_FORMAT(format);
+    exe = G_EXE_FORMAT(format);
+
+    if (!read_elf_header(format, &format->header, &format->is_32b, &format->endian))
+        goto gefa_error;
 
     /* Vérification des tailles d'entrée de table */
 
-    if (ELF_HDR(result, result->header, e_phentsize) != ELF_SIZEOF_PHDR(result))
+    if (ELF_HDR(format, format->header, e_phentsize) != ELF_SIZEOF_PHDR(format))
     {
         log_variadic_message(LMT_BAD_BINARY,
                              _("Corrupted program header size (%hu); fixed!" \
                                "  --  replacing 0x%04hx by 0x%04hx at offset 0x%x"),
-                             ELF_HDR(result, result->header, e_phentsize),
-                             ELF_HDR(result, result->header, e_phentsize),
-                             ELF_SIZEOF_PHDR(result),
-                             ELF_HDR_OFFSET_OF(result, e_phentsize));
+                             ELF_HDR(format, format->header, e_phentsize),
+                             ELF_HDR(format, format->header, e_phentsize),
+                             ELF_SIZEOF_PHDR(format),
+                             ELF_HDR_OFFSET_OF(format, e_phentsize));
 
-        ELF_HDR_SET(result, result->header, e_phentsize, ELF_SIZEOF_PHDR(result));
+        ELF_HDR_SET(format, format->header, e_phentsize, ELF_SIZEOF_PHDR(format));
 
     }
 
-    if (ELF_HDR(result, result->header, e_shentsize) != ELF_SIZEOF_SHDR(result))
+    if (ELF_HDR(format, format->header, e_shentsize) != ELF_SIZEOF_SHDR(format))
     {
         log_variadic_message(LMT_BAD_BINARY,
                              _("Corrupted section header size (%hu); fixed!" \
                                "  --  replacing 0x%04hx by 0x%04hx at offset 0x%x"),
-                             ELF_HDR(result, result->header, e_shentsize),
-                             ELF_HDR(result, result->header, e_shentsize),
-                             ELF_SIZEOF_SHDR(result),
-                             ELF_HDR_OFFSET_OF(result, e_shentsize));
+                             ELF_HDR(format, format->header, e_shentsize),
+                             ELF_HDR(format, format->header, e_shentsize),
+                             ELF_SIZEOF_SHDR(format),
+                             ELF_HDR_OFFSET_OF(format, e_shentsize));
 
-        ELF_HDR_SET(result, result->header, e_shentsize, ELF_SIZEOF_SHDR(result));
+        ELF_HDR_SET(format, format->header, e_shentsize, ELF_SIZEOF_SHDR(format));
 
     }
 
     /* Opérations spécifiques à l'architecture */
 
-    switch (ELF_HDR(result, result->header, e_machine))
+    switch (ELF_HDR(format, format->header, e_machine))
     {
         case EM_ARM:
-            result->ops.get_type_desc = (get_elf_prgm_type_desc_cb)get_elf_program_arm_type_desc;
-            result->ops.fix_virt = (fix_elf_virt_addr_cb)fix_elf_arm_virtual_address;
-            result->ops.get_linkage_offset = (get_elf_linkage_offset_cb)retrieve_arm_linkage_offset;
+            format->ops.get_type_desc = (get_elf_prgm_type_desc_cb)get_elf_program_arm_type_desc;
+            format->ops.fix_virt = (fix_elf_virt_addr_cb)fix_elf_arm_virtual_address;
+            format->ops.get_linkage_offset = (get_elf_linkage_offset_cb)retrieve_arm_linkage_offset;
             break;
 
         default:
             log_variadic_message(LMT_ERROR, "Architecture not supported for ELF binaries");
-            goto gefn_error;
+            goto gefa_error;
             break;
 
     }
@@ -323,23 +377,20 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus
 
     preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
 
+    if (!load_elf_symbols(format, status))
+        goto gefa_error;
 
-    if (!load_elf_symbols(result, status))
-        goto gefn_error;
+    if (!find_all_elf_strings(format))
+        goto gefa_error;
 
-    if (!find_all_elf_strings(result))
-        goto gefn_error;
+    if (!g_executable_format_complete_loading(exe, status))
+        goto gefa_error;
 
-    if (!g_executable_format_complete_loading(exe_format, status))
-        goto gefn_error;
+    result = true;
 
-    return base;
+ gefa_error:
 
- gefn_error:
-
-    g_object_unref(G_OBJECT(result));
-
-    return NULL;
+    return result;
 
 }
 
diff --git a/plugins/elf/format.h b/plugins/elf/format.h
index a822105..47b3171 100644
--- a/plugins/elf/format.h
+++ b/plugins/elf/format.h
@@ -59,7 +59,7 @@ FormatMatchStatus elf_is_matching(GBinContent *, GExeFormat *, void *, char **);
 GType g_elf_format_get_type(void);
 
 /* Prend en charge un nouveau format ELF. */
-GBinFormat *g_elf_format_new(GBinContent *, GExeFormat *, GtkStatusStack *);
+GExeFormat *g_elf_format_new(GBinContent *);
 
 /* Présente l'en-tête ELF du format chargé. */
 const elf_header *g_elf_format_get_header(const GElfFormat *);
diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c
index a3d8758..2d5bfd8 100644
--- a/plugins/elf/python/format.c
+++ b/plugins/elf/python/format.c
@@ -72,67 +72,17 @@ static PyObject *py_elf_format_new(PyTypeObject *type, PyObject *args, PyObject
 {
     PyObject *result;                       /* Instance à retourner        */
     PyObject *content_obj;                  /* Objet pour le contenu       */
-    PyObject *parent_obj;                   /* Objet pour le parent        */
-    PyObject *status_obj;                   /* Objet pour la progression   */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Instance GLib du contenu    */
-    GExeFormat *parent;                     /* Instance GLib du parent     */
-    GtkStatusStack *status;                 /* Instance GTK de suivi       */
-    GBinFormat *format;                     /* Création GLib à transmettre */
+    GExeFormat *format;                     /* Création GLib à transmettre */
 
-    parent_obj = Py_None;
-    status_obj = Py_None;
-
-    ret = PyArg_ParseTuple(args, "O|OO", &content_obj, &parent_obj, &status_obj);
+    ret = PyArg_ParseTuple(args, "O!", get_python_binary_content_type(), &content_obj);
     if (!ret) return NULL;
 
-    ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type());
-    if (!ret)
-    {
-        PyErr_SetString(PyExc_TypeError, _("The first argument must be an instance of BinContent."));
-        return NULL;
-    }
-
     content = G_BIN_CONTENT(pygobject_get(content_obj));
 
-    if (parent_obj == Py_None)
-        parent = NULL;
-
-    else
-    {
-        ret = PyObject_IsInstance(parent_obj, (PyObject *)get_python_executable_format_type());
-        if (!ret)
-        {
-            PyErr_SetString(PyExc_TypeError, _("The second argument must be a container format or None."));
-            return NULL;
-        }
-
-        parent = G_EXE_FORMAT(pygobject_get(parent_obj));
-
-    }
-
-    if (status_obj == Py_None)
-        status = NULL;
-
-    else
-    {
-        ret = PyObject_IsInstance(status_obj, (PyObject *)get_python_binary_content_type());
-        if (!ret)
-        {
-            PyErr_SetString(PyExc_TypeError, _("The third argument must be a status bar object or None."));
-            return NULL;
-        }
-
-        status = GTK_STATUS_STACK(pygobject_get(status_obj));
-
-    }
-
-    format = g_elf_format_new(content, parent, status);
-    if (format == NULL)
-    {
-        PyErr_SetString(PyExc_RuntimeError, _("Unable to load the ELF format."));
-        return NULL;
-    }
+    format = g_elf_format_new(content);
+    assert(format != NULL);
 
     result = pygobject_new(G_OBJECT(format));
 
diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am
index 5c3c46c..61d2c94 100644
--- a/plugins/pychrysalide/analysis/Makefile.am
+++ b/plugins/pychrysalide/analysis/Makefile.am
@@ -6,6 +6,7 @@ libpychrysaanalysis_la_SOURCES =		\
 	block.h block.c						\
 	content.h content.c					\
 	loaded.h loaded.c					\
+	loading.h loading.c					\
 	module.h module.c					\
 	project.h project.c					\
 	routine.h routine.c					\
diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c
index 6be767c..1ca5b3c 100644
--- a/plugins/pychrysalide/analysis/binary.c
+++ b/plugins/pychrysalide/analysis/binary.c
@@ -34,8 +34,8 @@
 #include <analysis/binary.h>
 
 
-#include "content.h"
 #include "../helpers.h"
+#include "../format/executable.h"
 
 
 
@@ -45,12 +45,6 @@ static PyObject *py_loaded_binary_new(PyTypeObject *, PyObject *, PyObject *);
 /* Fournit le nom associé à l'élément binaire. */
 static PyObject *py_loaded_binary_get_name(PyObject *, void *);
 
-/* Lance l'analyse d'un élément binaire chargé. */
-static PyObject *py_loaded_binary_analyse(PyObject *, PyObject *);
-
-/* Lance l'analyse d'un binaire chargé et attend sa conclusion. */
-static PyObject *py_loaded_binary_analyse_and_wait(PyObject *, PyObject *);
-
 /* Fournit le format de fichier reconnu dans le contenu binaire. */
 static PyObject *py_loaded_binary_get_format(PyObject *, void *);
 
@@ -79,23 +73,18 @@ static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *, void *);
 static PyObject *py_loaded_binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *result;                       /* Instance à retourner        */
-    PyObject *content_obj;                  /* Objet pour le contenu       */
+    PyObject *format_obj;                   /* Objet pour le contenu       */
     int ret;                                /* Bilan de lecture des args.  */
-    GBinContent *content;                   /* Instance GLib correspondante*/
-    GLoadedBinary *binary;                  /* Version GLib du format      */
+    GExeFormat *format;                     /* Instance GLib correspondante*/
+    GLoadedContent *binary;                 /* Version GLib du binaire     */
 
-    ret = PyArg_ParseTuple(args, "O", &content_obj);
+    ret = PyArg_ParseTuple(args, "O!", get_python_executable_format_type(), &format_obj);
     if (!ret) return NULL;
 
-    ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type());
-    if (ret == 0)
-    {
-        PyErr_SetString(PyExc_TypeError, _("Expected a BinContent as argument"));
-        return NULL;
-    }
+    format = G_EXE_FORMAT(pygobject_get(format_obj));
 
-    content = G_BIN_CONTENT(pygobject_get(content_obj));
-    binary = g_loaded_binary_new(content);
+    g_object_ref(G_OBJECT(format));
+    binary = g_loaded_binary_new(format);
 
     result = pygobject_new(G_OBJECT(binary));
 
@@ -138,58 +127,6 @@ static PyObject *py_loaded_binary_get_name(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self = contenu binaire à manipuler.                          *
-*                args = non utilisé ici.                                      *
-*                                                                             *
-*  Description : Lance l'analyse d'un élément binaire chargé.                 *
-*                                                                             *
-*  Retour      : Rien (None).                                                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_loaded_binary_analyse(PyObject *self, PyObject *args)
-{
-    GLoadedBinary *binary;                  /* Version GLib du format      */
-
-    binary = G_LOADED_BINARY(pygobject_get(self));
-
-    g_loaded_binary_analyse(binary);
-
-    Py_RETURN_NONE;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = contenu binaire à manipuler.                          *
-*                args = non utilisé ici.                                      *
-*                                                                             *
-*  Description : Lance l'analyse d'un binaire chargé et attend sa conclusion. *
-*                                                                             *
-*  Retour      : Rien (None).                                                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_loaded_binary_analyse_and_wait(PyObject *self, PyObject *args)
-{
-    GLoadedBinary *binary;                  /* Version GLib du format      */
-
-    binary = G_LOADED_BINARY(pygobject_get(self));
-
-    g_loaded_binary_analyse_and_wait(binary);
-
-    Py_RETURN_NONE;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
@@ -296,18 +233,6 @@ static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *self, void *c
 PyTypeObject *get_python_loaded_binary_type(void)
 {
     static PyMethodDef py_loaded_binary_methods[] = {
-        {
-            "analyse", py_loaded_binary_analyse,
-            METH_NOARGS,
-            "analyse(/)\n--\n\nStart the analysis of the loaded binary and " \
-            "send a \"disassembly-done\" signal when done."
-        },
-        {
-            "analyse_and_wait", py_loaded_binary_analyse_and_wait,
-            METH_NOARGS,
-            "analyse_and_wait(/)\n--\n\nRun the analysis of the loaded binary and " \
-            "wait for its completion."
-        },
         { NULL }
     };
 
diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c
index b38025a..328bf7b 100644
--- a/plugins/pychrysalide/analysis/loaded.c
+++ b/plugins/pychrysalide/analysis/loaded.c
@@ -36,6 +36,12 @@
 
 
 
+/* Lance l'analyse propre à l'élément chargé. */
+static PyObject *py_loaded_content_analyze(PyObject *, PyObject *);
+
+/* Lance l'analyse de l'élément chargé et attend sa conclusion. */
+static PyObject *py_loaded_content_analyze_and_wait(PyObject *, PyObject *);
+
 /* Détermine le nombre de vues disponibles pour un contenu. */
 static PyObject *py_loaded_content_count_views(PyObject *, PyObject *);
 
@@ -43,6 +49,63 @@ static PyObject *py_loaded_content_count_views(PyObject *, PyObject *);
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self = contenu binaire à manipuler.                          *
+*                args = non utilisé ici.                                      *
+*                                                                             *
+*  Description : Lance l'analyse propre à l'élément chargé.                   *
+*                                                                             *
+*  Retour      : Rien (None).                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_analyze(PyObject *self, PyObject *args)
+{
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    g_loaded_content_analyze(content);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = contenu binaire à manipuler.                          *
+*                args = non utilisé ici.                                      *
+*                                                                             *
+*  Description : Lance l'analyse de l'élément chargé et attend sa conclusion. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    bool status;                            /* Bilan de l'opération        */
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    status = g_loaded_content_analyze_and_wait(content);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self = contenu chargé à manipuler.                           *
 *                args = non utilisé ici.                                      *
 *                                                                             *
@@ -57,7 +120,7 @@ static PyObject *py_loaded_content_count_views(PyObject *, PyObject *);
 static PyObject *py_loaded_content_count_views(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    GLoadedContent *content;                /* Version GLib du format      */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
     size_t count;                           /* Quantité à retourner        */
 
     content = G_LOADED_CONTENT(pygobject_get(self));
@@ -87,6 +150,18 @@ PyTypeObject *get_python_loaded_content_type(void)
 {
     static PyMethodDef py_loaded_content_methods[] = {
         {
+            "analyze", py_loaded_content_analyze,
+            METH_NOARGS,
+            "analyze($self, /)\n--\n\nStart the analysis of the loaded binary and " \
+            "send a \"disassembly-done\" signal when done."
+        },
+        {
+            "analyze_and_wait", py_loaded_content_analyze_and_wait,
+            METH_NOARGS,
+            "analyze_and_wait($self, /)\n--\n\nRun the analysis of the loaded binary and " \
+            "wait for its completion."
+        },
+        {
             "count_views", py_loaded_content_count_views,
             METH_NOARGS,
             "count_views($self, /)\n--\n\nCompute the quantity of available views."
diff --git a/plugins/pychrysalide/analysis/loading.c b/plugins/pychrysalide/analysis/loading.c
new file mode 100644
index 0000000..fca9929
--- /dev/null
+++ b/plugins/pychrysalide/analysis/loading.c
@@ -0,0 +1,196 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * loading.c - équivalent Python du fichier "analysis/loading.c"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "loading.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/loading.h>
+
+
+#include "../helpers.h"
+
+
+
+/* --------------------- EXPLORATION NON BLOQUANTE DES CONTENUS --------------------- */
+
+
+
+/* ------------------- RESOLUTION DE CONTENUS BINAIRES EN CHARGES ------------------- */
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       EXPLORATION NON BLOQUANTE DES CONTENUS                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_content_explorer_type(void)
+{
+    static PyMethodDef py_content_explorer_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_content_explorer_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_content_explorer_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.ContentExplorer",
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = "PyChrysalide content explorer",
+
+        .tp_methods     = py_content_explorer_methods,
+        .tp_getset      = py_content_explorer_getseters
+
+    };
+
+    return &py_content_explorer_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide...ContentExplorer'.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_content_explorer(PyObject *module)
+{
+    PyTypeObject *py_content_explorer_type; /* Type 'ContentExplorer'      */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    py_content_explorer_type = get_python_content_explorer_type();
+
+    dict = PyModule_GetDict(module);
+
+    if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_EXPLORER, py_content_explorer_type, &PyGObject_Type))
+        return false;
+
+    return true;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                     RESOLUTION DE CONTENUS BINAIRES EN CHARGES                     */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_content_resolver_type(void)
+{
+    static PyMethodDef py_content_resolver_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_content_resolver_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_content_resolver_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.ContentResolver",
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = "PyChrysalide content resolver",
+
+        .tp_methods     = py_content_resolver_methods,
+        .tp_getset      = py_content_resolver_getseters
+
+    };
+
+    return &py_content_resolver_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide...ContentResolver'.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_content_resolver(PyObject *module)
+{
+    PyTypeObject *py_content_resolver_type; /* Type 'ContentResolver'      */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    py_content_resolver_type = get_python_content_resolver_type();
+
+    dict = PyModule_GetDict(module);
+
+    if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_RESOLVER, py_content_resolver_type, &PyGObject_Type))
+        return false;
+
+    return true;
+
+}
diff --git a/plugins/pychrysalide/analysis/loading.h b/plugins/pychrysalide/analysis/loading.h
new file mode 100644
index 0000000..56cdd21
--- /dev/null
+++ b/plugins/pychrysalide/analysis/loading.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * loading.h - prototypes pour l'équivalent Python du fichier "analysis/loading.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_LOADING_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_LOADING_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* --------------------- EXPLORATION NON BLOQUANTE DES CONTENUS --------------------- */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_content_explorer_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.ContentExplorer'. */
+bool register_python_content_explorer(PyObject *);
+
+
+
+/* ------------------- RESOLUTION DE CONTENUS BINAIRES EN CHARGES ------------------- */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_content_resolver_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.ContentResolver'. */
+bool register_python_content_resolver(PyObject *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_LOADING_H */
diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c
index a77121b..c9ab1e5 100644
--- a/plugins/pychrysalide/analysis/module.c
+++ b/plugins/pychrysalide/analysis/module.c
@@ -32,6 +32,7 @@
 #include "block.h"
 #include "content.h"
 #include "loaded.h"
+#include "loading.h"
 #include "project.h"
 #include "routine.h"
 #include "type.h"
@@ -90,6 +91,8 @@ bool add_analysis_module_to_python_module(PyObject *super)
     result &= register_python_binary_content(module);
     result &= register_python_loaded_content(module);
 
+    result &= register_python_content_explorer(module);
+    result &= register_python_content_resolver(module);
     result &= register_python_loaded_binary(module);
     result &= register_python_instr_block(module);
     result &= register_python_binary_routine(module);
diff --git a/plugins/pychrysalide/analysis/project.c b/plugins/pychrysalide/analysis/project.c
index cd7578d..fa7de72 100644
--- a/plugins/pychrysalide/analysis/project.c
+++ b/plugins/pychrysalide/analysis/project.c
@@ -32,18 +32,66 @@
 #include <analysis/project.h>
 
 
+#include "loaded.h"
 #include "../helpers.h"
 
 
 
+/* Crée un nouvel objet Python de type 'StudyProject'. */
+static PyObject *py_study_project_new(PyTypeObject *, PyObject *, PyObject *);
+
 /* Procède à l'enregistrement d'un projet donné. */
 static PyObject *py_study_project_save(PyObject *, PyObject *);
 
+/* Attache un contenu donné à un projet donné. */
+static PyObject *py_study_project_attach_content(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type de l'objet à instancier.                         *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Crée un nouvel objet Python de type 'StudyProject'.          *
+*                                                                             *
+*  Retour      : Instance Python mise en place.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_study_project_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    const char *filename;                   /* Destination de la sauvegarde*/
+    int ret;                                /* Bilan de lecture des args.  */
+    GStudyProject *project;                 /* Version GLib du projet      */
+
+    filename = NULL;
+
+    ret = PyArg_ParseTuple(args, "|s", &filename);
+    if (!ret) return NULL;
+
+    if (filename != NULL)
+        project = g_study_project_open(filename);
+    else
+        project = g_study_project_new();
+
+    result = pygobject_new(G_OBJECT(project));
+
+    if (project != NULL)
+        g_object_unref(project);
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self = contenu binaire à manipuler.                          *
+*  Paramètres  : self = projet d'étude à manipuler.                           *
 *                args = arguments accompagnant l'appel.                       *
 *                                                                             *
 *  Description : Procède à l'enregistrement d'un projet donné.                *
@@ -80,6 +128,41 @@ static PyObject *py_study_project_save(PyObject *self, PyObject *args)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self = projet d'étude à manipuler.                           *
+*                args = arguments accompagnant l'appel.                       *
+*                                                                             *
+*  Description : Attache un contenu donné à un projet donné.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_study_project_attach_content(PyObject *self, PyObject *args)
+{
+    GStudyProject *project;                 /* Version GLib du format      */
+    PyObject *content_obj;                  /* Objet pour le contenu       */
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedContent *content;                /* Instance GLib correspondante*/
+
+    project = G_STUDY_PROJECT(pygobject_get(self));
+    assert(project != NULL);
+
+    ret = PyArg_ParseTuple(args, "O!", get_python_loaded_content_type(), &content_obj);
+    if (!ret) return NULL;
+
+    content = G_LOADED_CONTENT(pygobject_get(content_obj));
+
+    g_study_project_attach_content(project, content);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -98,6 +181,11 @@ PyTypeObject *get_python_study_project_type(void)
             METH_VARARGS,
             "save($self, filename, /)\n--\n\nSave the project into a given file."
         },
+        {
+            "attach", py_study_project_attach_content,
+            METH_VARARGS,
+            "attach($self, loaded, /)\n--\n\nAdd a loaded content to the project."
+        },
         { NULL }
     };
 
@@ -116,7 +204,8 @@ PyTypeObject *get_python_study_project_type(void)
         .tp_doc         = "PyChrysalide study project",
 
         .tp_methods     = py_study_project_methods,
-        .tp_getset      = py_study_project_getseters
+        .tp_getset      = py_study_project_getseters,
+        .tp_new         = py_study_project_new
 
     };
 
diff --git a/plugins/pychrysalide/core/Makefile.am b/plugins/pychrysalide/core/Makefile.am
index bc21d77..999674d 100644
--- a/plugins/pychrysalide/core/Makefile.am
+++ b/plugins/pychrysalide/core/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libpychrysacore.la
 libpychrysacore_la_SOURCES =			\
 	demanglers.h demanglers.c			\
 	formats.h formats.c					\
+	global.h global.c					\
 	logs.h logs.c						\
 	module.h module.c					\
 	params.h params.c
diff --git a/plugins/pychrysalide/core/global.c b/plugins/pychrysalide/core/global.c
new file mode 100644
index 0000000..0fe767f
--- /dev/null
+++ b/plugins/pychrysalide/core/global.c
@@ -0,0 +1,280 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * global.c - équivalent Python du fichier "core/global.c"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "global.h"
+
+
+#include <pygobject.h>
+
+
+#include <core/global.h>
+
+
+#include "../helpers.h"
+#include "../analysis/project.h"
+
+
+
+/* Fournit l'adresse de l'explorateur de contenus courant. */
+static PyObject *py_global_get_content_explorer(PyObject *, void *);
+
+/* Fournit l'adresse du résolveur de contenus courant. */
+static PyObject *py_global_get_content_resolver(PyObject *, void *);
+
+/* Fournit l'adresse du projet courant. */
+static PyObject *py_global_get_current_project(PyObject *, void *);
+
+/* Définit l'adresse du projet courant. */
+static int py_global_set_current_project(PyObject *, PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit l'adresse de l'explorateur de contenus courant.      *
+*                                                                             *
+*  Retour      : Adresse de l'explorateur global ou None si aucun (!).        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_global_get_content_explorer(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GContentExplorer *explorer;             /* Gestionnaire natif récupéré */
+
+    explorer = get_current_content_explorer();
+
+    if (explorer != NULL)
+    {
+        result = pygobject_new(G_OBJECT(explorer));
+        g_object_unref(G_OBJECT(explorer));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit l'adresse du résolveur de contenus courant.          *
+*                                                                             *
+*  Retour      : Adresse du résolveur global ou None si aucun (!).            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_global_get_content_resolver(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GContentResolver *resolver;             /* Gestionnaire natif récupéré */
+
+    resolver = get_current_content_resolver();
+
+    if (resolver != NULL)
+    {
+        result = pygobject_new(G_OBJECT(resolver));
+        g_object_unref(G_OBJECT(resolver));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit l'adresse du projet courant.                         *
+*                                                                             *
+*  Retour      : Adresse du résolveur global ou None si aucun.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_global_get_current_project(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GStudyProject *project;                 /* Projet courant récupéré     */
+
+    project = get_current_project();
+
+    if (project != NULL)
+    {
+        result = pygobject_new(G_OBJECT(project));
+        g_object_unref(G_OBJECT(project));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    printf("result: %p (project=%p)\n", result, project);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Définit l'adresse du projet courant.                         *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_global_set_current_project(PyObject *self, PyObject *value, void *closure)
+{
+    int ret;                                /* Bilan d'analyse             */
+    GStudyProject *project;                 /* Version GLib du format      */
+
+    ret = PyObject_IsInstance(value, (PyObject *)get_python_study_project_type());
+    if (!ret) return -1;
+
+    project = G_STUDY_PROJECT(pygobject_get(value));
+
+    g_object_ref(G_OBJECT(project));
+
+    set_current_project(project);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_global_type(void)
+{
+    static PyMethodDef py_global_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_global_getseters[] = {
+        {
+            "content_explorer", py_global_get_content_explorer, NULL,
+            "Get the global exploration manager discovering contents.", NULL
+        },
+        {
+            "content_resolver", py_global_get_content_resolver, NULL,
+            "Get the global resolution manager translating binary contents into loaded contents.", NULL
+        },
+        {
+            "current_project", py_global_get_current_project, py_global_set_current_project,
+            "Get or set the current global project.", NULL
+        },
+        { NULL }
+    };
+
+    static PyTypeObject py_global_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name = "pychrysalide.core._global",
+        .tp_basicsize = sizeof(PyObject),
+
+        .tp_flags = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc = "Access to the global properties",
+
+        .tp_methods = py_global_methods,
+        .tp_getset  = py_global_getseters
+
+    };
+
+    return &py_global_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.core._global'.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_global(PyObject *module)
+{
+    PyTypeObject *py_global_type;           /* Type Python de 'global'     */
+    int ret;                                /* Bilan d'un appel            */
+
+    py_global_type = get_python_global_type();
+
+    py_global_type->tp_new = PyType_GenericNew;
+
+    if (PyType_Ready(py_global_type) != 0)
+        return false;
+
+    Py_INCREF(py_global_type);
+    ret = PyModule_AddObject(module, "_global", (PyObject *)py_global_type);
+
+    return (ret == 0);
+
+}
diff --git a/plugins/pychrysalide/core/global.h b/plugins/pychrysalide/core/global.h
new file mode 100644
index 0000000..b136cdb
--- /dev/null
+++ b/plugins/pychrysalide/core/global.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * global.h - prototypes pour l'équivalent Python du fichier "core/global.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_CORE_GLOBAL_H
+#define _PLUGINS_PYCHRYSALIDE_CORE_GLOBAL_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_global_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.core._global'. */
+bool register_python_global(PyObject *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_CORE_GLOBAL_H */
diff --git a/plugins/pychrysalide/core/module.c b/plugins/pychrysalide/core/module.c
index dd89ea0..22d9a48 100644
--- a/plugins/pychrysalide/core/module.c
+++ b/plugins/pychrysalide/core/module.c
@@ -30,6 +30,7 @@
 
 #include "demanglers.h"
 #include "formats.h"
+#include "global.h"
 #include "logs.h"
 #include "params.h"
 #include "../access.h"
@@ -84,6 +85,7 @@ bool add_core_module_to_python_module(PyObject *super)
 
     result &= register_python_demanglers(module);
     result &= register_python_formats(module);
+    result &= register_python_global(module);
     result &= register_python_logs(module);
     result &= register_python_params(module);
 
diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index 1b1bfe8..9ae45ff 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -28,7 +28,7 @@
 #include <pygobject.h>
 
 
-#include <format/format.h>
+#include <format/executable.h>
 
 
 #include "format.h"
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index fad0084..4689d0c 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -76,6 +76,9 @@ static bool g_python_plugin_do_init(GPythonPlugin *);
 /* Procède à l'extinction du greffon. */
 static bool g_python_plugin_do_exit(GPythonPlugin *, GObject *);
 
+/* Procède à une opération liée à un contenu binaire. */
+static void g_python_plugin_handle_binary_content(const GPythonPlugin *, PluginAction, GBinContent *, gid_t, GtkStatusStack *);
+
 /* Indique si le format peut être pris en charge ici. */
 FormatMatchStatus python_plugin_is_matching(GBinContent *, GExeFormat *, GPythonPlugin *, char **);
 
@@ -285,6 +288,27 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 
                 switch (sub)
                 {
+                    case DPS_CONTENT:
+
+                        switch (action)
+                        {
+                            case PGA_CONTENT_EXPLORER:
+                            case PGA_CONTENT_RESOLVER:
+                                if (!register_python_binding(instance, handle_content, \
+                                                             (pg_handle_content)g_python_plugin_handle_binary_content))
+                                    goto gppn_bad_plugin;
+                                break;
+
+                            default:
+                                log_variadic_message(LMT_WARNING,
+                                                     _("Unknown action '0x%02x' in plugin '%s'..."),
+                                                     action, filename);
+                                break;
+
+                        }
+
+                        break;
+
                     case DPS_FORMAT:
 
                         switch (action)
@@ -439,7 +463,7 @@ static bool g_python_plugin_read_interface(GPythonPlugin *plugin)
     {
         action = PyList_GET_ITEM(tuple, i);
 
-        interface.actions[i] = PyLong_AsLong(action);
+        interface.actions[i] = PyLong_AsUnsignedLong(action);
 
     }
 
@@ -543,6 +567,42 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                gid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
+{
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
+
+    args = PyTuple_New(4);
+
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
+
+    value = run_python_method(plugin->instance, "handle_binary_content", args);
+
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
 *                parent  = éventuel format exécutable déjà chargé.            *
 *                plugin  = grefon C interne représentant le grefon Python.    *
@@ -678,7 +738,7 @@ static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAc
 
     args = PyTuple_New(2);
 
-    PyTuple_SetItem(args, 0, PyLong_FromLong(action));
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
     PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary)));
 
     value = run_python_method(plugin->instance, "process_binary_disassembly", args);
@@ -716,6 +776,8 @@ static bool py_plugin_module_define_constants(PyTypeObject *obj_type)
     result &= PyDict_AddIntMacro(obj_type, PGA_BASIC_NONE);
     result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_INIT);
     result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_EXIT);
+    result &= PyDict_AddIntMacro(obj_type, PGA_CONTENT_EXPLORER);
+    result &= PyDict_AddIntMacro(obj_type, PGA_CONTENT_RESOLVER);
     result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_MATCHER);
     result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_LOADER_LAST);
     result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_STARTED);
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index d7cb29c..38cb503 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -120,19 +120,16 @@ static void g_loaded_binary_dispose(GLoadedBinary *);
 /* Procède à la libération totale de la mémoire. */
 static void g_loaded_binary_finalize(GLoadedBinary *);
 
-/* Acquitte la fin d'un désasemblage différé et complet. */
-static void ack_completed_disassembly(GDelayedDisassembly *, GLoadedBinary *);
-
 
 
 /* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */
 
 
 /* Charge en mémoire les formes d'enregistrement du XML. */
-static bool g_loaded_binary_load_storage(GLoadedBinary *, xmlXPathContextPtr, const char *);
+static bool g_loaded_binary_load_storage(GLoadedBinary *, xmlXPathContext *, const char *);
 
 /* Ecrit les formes d'enregistrement du binaire dans du XML. */
-static bool g_loaded_binary_save_storage(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *);
+static bool g_loaded_binary_save_storage(const GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *);
 
 /* Etablit une connexion au serveur interne en tant que client. */
 static bool g_loaded_binary_connect_internal(GLoadedBinary *);
@@ -146,13 +143,26 @@ static bool g_loaded_binary_connect_remote(GLoadedBinary *);
 
 
 
-/* Lance l'analyse d'un élément binaire chargé. */
-static void _g_loaded_binary_analyse(GLoadedBinary *, disassembly_ack_fc);
 
 
 /* ---------------------- GESTION SOUS FORME DE CONTENU CHARGE ---------------------- */
 
 
+/* Interprète un contenu binaire chargé avec un appui XML. */
+static bool g_loaded_binary_restore(GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Ecrit une sauvegarde du binaire dans un fichier XML. */
+static bool g_loaded_binary_save(const GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Fournit le contenu représenté de l'élément chargé. */
+static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *);
+
+/* Fournit le contenu représenté de l'élément chargé. */
+static const char *g_loaded_binary_get_format_name(const GLoadedBinary *);
+
+/* Assure le désassemblage en différé. */
+static bool g_loaded_binary_analyze(GLoadedBinary *, wgroup_id_t, GtkStatusStack *);
+
 /* Fournit le désignation associée à l'élément chargé. */
 static const char *g_loaded_binary_describe(const GLoadedBinary *, bool);
 
@@ -269,6 +279,14 @@ static void g_loaded_binary_init(GLoadedBinary *binary)
 
 static void g_loaded_binary_interface_init(GLoadedContentInterface *iface)
 {
+    iface->restore = (restore_content_fc)g_loaded_binary_restore;
+    iface->save = (save_content_fc)g_loaded_binary_save;
+
+    iface->get_content = (get_content_fc)g_loaded_binary_get_content;
+    iface->get_format_name = (get_format_name_fc)g_loaded_binary_get_format_name;
+
+    iface->analyze = (analyze_loaded_fc)g_loaded_binary_analyze;
+
     iface->describe = (describe_loaded_fc)g_loaded_binary_describe;
 
     iface->count_views = (count_loaded_views_fc)g_loaded_binary_count_views;
@@ -333,6 +351,32 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = format d'exécutable établi.                         *
+*                                                                             *
+*  Description : Interprète un contenu binaire chargé.                        *
+*                                                                             *
+*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GLoadedContent *g_loaded_binary_new(GExeFormat *format)
+{
+    GLoadedBinary *result;                  /* Adresse à retourner         */
+
+    result = g_object_new(G_TYPE_LOADED_BINARY, NULL);
+
+    result->format = format;
+
+    return G_LOADED_CONTENT(result);
+
+}
+
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content = contenu binaire chargé en mémoire.                 *
 *                                                                             *
 *  Description : Interprète un contenu binaire chargé.                        *
@@ -343,7 +387,7 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-GLoadedBinary *g_loaded_binary_new(GBinContent *content)
+GLoadedBinary *g_loaded_binary_new_old(GBinContent *content)
 {
     GLoadedBinary *result;                  /* Adresse à retourner         */
     FormatMatchStatus status;               /* Statut d'une reconnaissance */
@@ -420,198 +464,6 @@ GLoadedBinary *g_loaded_binary_new(GBinContent *content)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : context = contexte pour les recherches XPath.                *
-*                path    = chemin d'accès au noeud XML à lire.                *
-*                project = projet dans lequel venir rechercher les contenus.  *
-*                                                                             *
-*  Description : Interprète un contenu binaire chargé avec un appui XML.      *
-*                                                                             *
-*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path, GStudyProject *project)
-{
-    GLoadedBinary *result;                  /* Adresse à retourner         */
-    char *content_path;                     /* Partie "Contenus"           */
-    char *access;                           /* Chemin d'accès à un élément */
-    char *hash;                             /* Empreinte à retrouver       */
-    GBinContent *content;                   /* Contenu à référencer        */
-    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
-    unsigned int i;                         /* Boucle de parcours          */
-    bool attached;                          /* Bilan d'un chargement       */
-
-    /* Contenus binaires associés */
-
-    content_path = strdup(path);
-    content_path = stradd(content_path, "/Contents");
-
-    access = strdup(content_path);
-    access = stradd(access, "/Main");
-
-    hash = get_node_text_value(context, access);
-
-    free(access);
-
-    if (hash == NULL)
-        goto glbnfx_early_error;
-
-    content = g_study_project_find_binary_content_by_hash(project, hash);
-
-    free(hash);
-
-    if (content == NULL)
-        goto glbnfx_early_error;
-
-    result = g_loaded_binary_new(content);
-
-    g_object_unref(G_OBJECT(content));
-
-    if (result == NULL)
-        goto glbnfx_early_error;
-
-    asprintf(&access, "%s/DebugInfo", content_path);
-
-    xobject = get_node_xpath_object(context, access);
-
-    free(access);
-
-    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
-    {
-        asprintf(&access, "%s/DebugInfo[position()=%u]", content_path, i + 1);
-
-        hash = get_node_text_value(context, access);
-
-        free(access);
-
-        if (hash == NULL)
-            goto glbnfx_error;
-
-        content = g_study_project_find_binary_content_by_hash(project, hash);
-
-        free(hash);
-
-        if (content == NULL)
-            goto glbnfx_error;
-
-        attached = g_loaded_binary_attach_debug_info(result, content);
-
-        g_object_unref(G_OBJECT(content));
-
-        if (!attached)
-            goto glbnfx_error;
-
-    }
-
-    if(xobject != NULL)
-        xmlXPathFreeObject(xobject);
-
-    free(content_path);
-
-    /* Elément divers associés au binaire */
-
-    if (!g_loaded_binary_load_storage(result, context, path))
-        goto glbnfx_final_error;
-
-    return result;
-
- glbnfx_error:
-
-    free(content_path);
-
- glbnfx_final_error:
-
-    g_object_unref(G_OBJECT(result));
-
-    return NULL;
-
- glbnfx_early_error:
-
-    g_object_unref(G_OBJECT(result));
-
-    free(content_path);
-
-    return NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary  = élément binaire à traiter.                         *
-*                xdoc    = structure XML en cours d'édition.                  *
-*                context = contexte à utiliser pour les recherches.           *
-*                path    = chemin d'accès réservé au binaire.                 *
-*                base    = référence au lieu d'enregistrement du projet.      *
-*                                                                             *
-*  Description : Ecrit une sauvegarde du binaire dans un fichier XML.         *
-*                                                                             *
-*  Retour      : true si l'opération a bien tourné, false sinon.              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *base)
-{
-    bool result;                            /* Bilan à faire remonter      */
-    char *content_path;                     /* Partie "Contenus"           */
-    char *access;                           /* Chemin d'accès à un élément */
-    GBinContent *content;                   /* Contenu à référencer        */
-    size_t debugs_count;                    /* Quantité de formats liés    */
-    size_t i;                               /* Boucle de parcours          */
-    GDbgFormat *debug;                      /* Informations de débogage    */
-
-    /* Contenus binaires associés */
-
-    content_path = strdup(path);
-    content_path = stradd(content_path, "/Contents");
-
-    asprintf(&access, "%s/Main", content_path);
-
-    content = g_binary_format_get_content(G_BIN_FORMAT(binary->format));
-    result = g_binary_content_save(content, xdoc, context, access, base);
-    g_object_unref(G_OBJECT(content));
-
-    free(access);
-
-    debugs_count = g_exe_format_count_debug_info(binary->format);
-
-    for (i = 0; i < debugs_count && result; i++)
-    {
-        asprintf(&access, "%s/DebugInfo[position()=%zu]", content_path, i);
-
-        debug = g_exe_format_get_debug_info(binary->format, i);
-
-        content = g_binary_format_get_content(G_BIN_FORMAT(debug));
-        result = g_binary_content_save(content, xdoc, context, access, base);
-        g_object_unref(G_OBJECT(content));
-
-        g_object_unref(G_OBJECT(debug));
-
-        free(access);
-
-    }
-
-    free(content_path);
-
-    /* Elément divers associés au binaire */
-
-    result = g_loaded_binary_save_storage(binary, xdoc, context, path);
-
-    /* Sauvegarde côté serveur */
-
-    g_db_client_save(binary->local);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : binary = élément binaire à consulter.                        *
 *                full   = précise s'il s'agit d'une version longue ou non.    *
 *                                                                             *
@@ -659,7 +511,7 @@ const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_loaded_binary_load_storage(GLoadedBinary *binary, xmlXPathContextPtr context, const char *path)
+static bool g_loaded_binary_load_storage(GLoadedBinary *binary, xmlXPathContext *context, const char *path)
 {
     bool result;                            /* Bilan à faire remonter      */
     char *storage_path;                     /* Partie "Enregistrement"     */
@@ -783,7 +635,7 @@ static bool g_loaded_binary_load_storage(GLoadedBinary *binary, xmlXPathContextP
 *                                                                             *
 ******************************************************************************/
 
-static bool g_loaded_binary_save_storage(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+static bool g_loaded_binary_save_storage(const GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path)
 {
     bool result;                            /* Bilan à faire remonter      */
     char *storage_path;                     /* Partie "Enregistrement"     */
@@ -1414,86 +1266,6 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures f
 
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary = élément binaire à traiter.                          *
-*                ack    = éventuelle fonction à appeler en conclusion.        *
-*                                                                             *
-*  Description : Lance l'analyse d'un élément binaire chargé.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void _g_loaded_binary_analyse(GLoadedBinary *binary, disassembly_ack_fc ack)
-{
-    /* Détermination de l'identifiant */
-
-
-
-    /* Contacts avec les serveurs */
-
-
-    // Déconnexion...
-
-    g_loaded_binary_connect_internal(binary);
-
-
-    disassemble_binary(binary, &binary->disass_cache, ack);
-
-
-
-    /* TODO : remme ! */
-    //ack_completed_disassembly(NULL, binary);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary = élément binaire à traiter.                          *
-*                                                                             *
-*  Description : Lance l'analyse d'un élément binaire chargé.                 *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_loaded_binary_analyse(GLoadedBinary *binary)
-{
-    _g_loaded_binary_analyse(binary, ack_completed_disassembly);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary = élément binaire à traiter.                          *
-*                                                                             *
-*  Description : Lance l'analyse d'un binaire chargé et attend sa conclusion. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_loaded_binary_analyse_and_wait(GLoadedBinary *binary)
-{
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
-
-    _g_loaded_binary_analyse(binary, NULL);
-
-    queue = get_work_queue();
-    g_work_queue_wait_for_completion(queue, DEFAULT_WORK_GROUP);
-
-    ack_completed_disassembly(NULL, binary);
-
-}
 
 
 /******************************************************************************
@@ -1682,80 +1454,183 @@ bool *g_loaded_binary_display_decomp_lines(GLoadedBinary *binary)
 }
 
 
+
+/* ---------------------------------------------------------------------------------- */
+/*                        GESTION SOUS FORME DE CONTENU CHARGE                        */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : disass = travail de désassemblage mené à bien.               *
-*                binary = représentation de binaire à l'origine de l'opérat°. *
+*  Paramètres  : binary  = élément binaire à traiter.                         *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé au binaire.                 *
 *                                                                             *
-*  Description : Acquitte la fin d'un désasemblage différé et complet.        *
+*  Description : Interprète un contenu binaire chargé avec un appui XML.      *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-#include "../gui/core/global.h"
-void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binary)
-{
-    //GRenderingLine *line;                   /* "Première" ligne de rendu   */
 
-    size_t i;                               /* Boucle de parcours          */
+static bool g_loaded_binary_restore(GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path)
+{
+    bool result;                            /* Bilan à faire remonter      */
 
-    const char * const *files;              /* Liste de fichiers source    */
+    /* Elément divers associés au binaire */
 
+    result = g_loaded_binary_load_storage(binary, context, path);
 
+    return result;
 
+}
 
-    g_binary_format_complete_analysis(G_BIN_FORMAT(binary->format), get_global_status());
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary  = élément binaire à traiter.                         *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé au binaire.                 *
+*                                                                             *
+*  Description : Ecrit une sauvegarde du binaire dans un fichier XML.         *
+*                                                                             *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path)
+{
+    bool result;                            /* Bilan à faire remonter      */
 
-    /* ... = *///g_loaded_binary_connect_internal(binary);
+    /* Elément divers associés au binaire */
 
+    result = g_loaded_binary_save_storage(binary, xdoc, context, path);
 
-    /* Décompilation... */
+    /* Sauvegarde côté serveur */
 
+    if (result)
+        g_db_client_save(binary->local);
 
+    return result;
 
-    files = g_binary_format_get_source_files(G_BIN_FORMAT(binary->format),
-                                             &binary->decbuf_count, &binary->defsrc);
+}
 
-#if 0
-    if (binary->decbuf_count > 0)
-    {
-        binary->dec_buffers = (GCodeBuffer **)calloc(binary->decbuf_count, sizeof(GCodeBuffer *));
 
-        /*
-        for (i = 0; i < binary->decbuf_count; i++)
-            binary->dec_buffers[i] = decompile_all_from_file(binary, files[i]);
-        */
-    }
-#endif
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = élément chargé à manipuler.                         *
+*                                                                             *
+*  Description : Fournit le contenu représenté de l'élément chargé.           *
+*                                                                             *
+*  Retour      : Contenu représenté.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *binary)
+{
+    GBinContent *result;                    /* Contenu interne à renvoyer  */
 
+    result = g_binary_format_get_content(G_BIN_FORMAT(binary->format));
 
-#if 0
-    g_rendering_line_merge(&binary->lines, &disass->lines);
+    return result;
 
+}
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = élément chargé à manipuler.                         *
+*                                                                             *
+*  Description : Fournit le contenu représenté de l'élément chargé.           *
+*                                                                             *
+*  Retour      : Contenu représenté.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    line = g_rendering_line_find_by_address(disass->lines, NULL,
-                                            g_exe_format_get_entry_point(binary->format));
-    if (line != NULL) g_rendering_line_add_flag(line, RLF_ENTRY_POINT);
+static const char *g_loaded_binary_get_format_name(const GLoadedBinary *binary)
+{
+    const char *result;                     /* Désignation à retourner     */
 
-    /* On réintègre le flot premier */
-#endif
+    result = g_binary_format_get_name(G_BIN_FORMAT(binary->format));
 
-    g_signal_emit_by_name(binary, "disassembly-done");
+    return result;
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = élément chargé dont l'analyse est lancée.           *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure le désassemblage en différé.                          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-/* ---------------------------------------------------------------------------------- */
-/*                        GESTION SOUS FORME DE CONTENU CHARGE                        */
-/* ---------------------------------------------------------------------------------- */
+static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinFormat *format;                     /* Format lié au binaire       */
+    const char *arch;                       /* Architecture d'exécution    */
+    const char *desc;                       /* Description humaine associée*/
+
+    /* Interprétation du format associé */
+
+    format = G_BIN_FORMAT(binary->format);
+
+    result = g_binary_format_analyze(format, gid, status);
+    if (!result) goto glba_exit;
+
+    /* Architecture visée */
+
+    arch = g_exe_format_get_target_machine(binary->format);
+    desc = get_arch_processor_name(arch);
+
+    if (desc == NULL)
+    {
+        log_simple_message(LMT_INFO, _("Unknown architecture"));
+        goto glba_exit;
+    }
+    else
+        log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
+
+    binary->proc = get_arch_processor_for_type(arch);
+
+    if (binary->proc == NULL)
+    {
+        log_simple_message(LMT_ERROR, _("Unable to load the required processor"));
+        goto glba_exit;
+    }
+
+    /* Phase de désassemblage pur */
+
+    g_loaded_binary_connect_internal(binary);
+
+    disassemble_binary(binary, gid, status, &binary->disass_cache);
+
+    g_binary_format_complete_analysis(format, status);
+
+    result = true;
+
+ glba_exit:
+
+    return result;
+
+}
 
 
 /******************************************************************************
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index ca62084..b57e072 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -29,22 +29,17 @@
 #include <stdbool.h>
 
 #include "content.h"
+#include "loaded.h"
 #include "db/collection.h"
 #include "db/client.h"
 #include "db/protocol.h"
 #include "../arch/processor.h"
-#include "../common/xml.h"
 #include "../format/debuggable.h"
 #include "../format/executable.h"
 #include "../glibext/gbuffercache.h"
 
 
 
-/* Redéfinition depuis project.c : projet d'étude regroupant les binaires analysés (instance) */
-typedef struct _GStudyProject GStudyProject;
-
-
-
 /* ------------------------ ENCADREMENTS D'UN BINAIRE CHARGE ------------------------ */
 
 
@@ -79,13 +74,10 @@ typedef enum _BinaryPartModel
 GType g_loaded_binary_get_type(void);
 
 /* Interprète un contenu binaire chargé. */
-GLoadedBinary *g_loaded_binary_new(GBinContent *);
-
-/* Interprète un contenu binaire chargé avec un appui XML. */
-GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr, const char *, GStudyProject *);
+GLoadedContent *g_loaded_binary_new(GExeFormat *);
 
-/* Ecrit une sauvegarde du binaire dans un fichier XML. */
-bool g_loaded_binary_save(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *);
+/* Interprète un contenu binaire chargé. */
+GLoadedBinary *g_loaded_binary_new_old(GBinContent *);
 
 /* Fournit le nom associé à l'élément binaire. */
 const char *g_loaded_binary_get_name(const GLoadedBinary *, bool);
@@ -160,12 +152,6 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbIte
 
 
 
-/* Lance l'analyse d'un élément binaire chargé. */
-void g_loaded_binary_analyse(GLoadedBinary *);
-
-/* Lance l'analyse d'un binaire chargé et attend sa conclusion. */
-void g_loaded_binary_analyse_and_wait(GLoadedBinary *);
-
 /* Fournit le format de fichier reconnu dans le contenu binaire. */
 bool g_loaded_binary_attach_debug_info(GLoadedBinary *, GBinContent *);
 
diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h
index e8b4add..49d5269 100644
--- a/src/analysis/content-int.h
+++ b/src/analysis/content-int.h
@@ -29,6 +29,9 @@
 
 
 
+/* Donne l'origine d'un contenu binaire. */
+typedef GBinContent * (* get_content_root_fc) (GBinContent *);
+
 /* Fournit le nom associé au contenu binaire. */
 typedef const char * (* describe_content_fc) (const GBinContent *, bool);
 
@@ -80,6 +83,8 @@ struct _GBinContentIface
 {
     GTypeInterface base_iface;              /* A laisser en premier        */
 
+    get_content_root_fc get_root;           /* Renvoie à l'origine         */
+
     describe_content_fc describe;           /* Fournit une description     */
 
     save_content_fc save;                   /* Sauvegarde du contenu       */
diff --git a/src/analysis/content.c b/src/analysis/content.c
index 2c2d366..3c394f1 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -99,6 +99,34 @@ GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const cha
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à consulter.                       *
+*                                                                             *
+*  Description : Donne l'origine d'un contenu binaire.                        *
+*                                                                             *
+*  Retour      : Contenu à l'origine du contenu courant.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_binary_content_get_root(GBinContent *content)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+    GBinContentIface *iface;                /* Interface utilisée          */
+
+    iface = G_BIN_CONTENT_GET_IFACE(content);
+
+    result = iface->get_root(content);
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
 *                full    = précise s'il s'agit d'une version longue ou non.   *
 *                                                                             *
 *  Description : Fournit le nom associé au contenu binaire.                   *
diff --git a/src/analysis/content.h b/src/analysis/content.h
index b06a17b..3f471f9 100644
--- a/src/analysis/content.h
+++ b/src/analysis/content.h
@@ -57,6 +57,9 @@ GType g_binary_content_get_type(void) G_GNUC_CONST;
 /* Charge en mémoire un contenu binaire à partir d'XML. */
 GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr, const char *, const char *);
 
+/* Donne l'origine d'un contenu binaire. */
+GBinContent *g_binary_content_get_root(GBinContent *);
+
 /* Fournit le nom associé au contenu binaire. */
 const char *g_binary_content_describe(const GBinContent *, bool);
 
diff --git a/src/analysis/contents/encapsulated.c b/src/analysis/contents/encapsulated.c
index 1fd4203..e307e6b 100644
--- a/src/analysis/contents/encapsulated.c
+++ b/src/analysis/contents/encapsulated.c
@@ -70,6 +70,9 @@ static void g_encaps_content_dispose(GEncapsContent *);
 /* Procède à la libération totale de la mémoire. */
 static void g_encaps_content_finalize(GEncapsContent *);
 
+/* Donne l'origine d'un contenu binaire. */
+static GBinContent *g_encaps_content_get_root(GEncapsContent *);
+
 /* Fournit le nom associé au contenu binaire. */
 static const char *g_encaps_content_describe(const GEncapsContent *, bool);
 
@@ -181,6 +184,8 @@ static void g_encaps_content_init(GEncapsContent *content)
 
 static void g_encaps_content_interface_init(GBinContentInterface *iface)
 {
+    iface->get_root = (get_content_root_fc)g_encaps_content_get_root;
+
     iface->describe = (describe_content_fc)g_encaps_content_describe;
 
     iface->save = (save_content_fc)g_encaps_content_save;
@@ -367,6 +372,29 @@ GBinContent *g_encaps_content_new_from_xml(xmlXPathContextPtr context, const cha
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à consulter.                       *
+*                                                                             *
+*  Description : Donne l'origine d'un contenu binaire.                        *
+*                                                                             *
+*  Retour      : Contenu à l'origine du contenu courant.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinContent *g_encaps_content_get_root(GEncapsContent *content)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+
+    result = g_binary_content_get_root(content->base);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
 *                full    = précise s'il s'agit d'une version longue ou non.   *
 *                                                                             *
 *  Description : Fournit le nom associé au contenu binaire.                   *
diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c
index 31acb6f..901a848 100644
--- a/src/analysis/contents/file.c
+++ b/src/analysis/contents/file.c
@@ -73,6 +73,9 @@ static void g_file_content_dispose(GFileContent *);
 /* Procède à la libération totale de la mémoire. */
 static void g_file_content_finalize(GFileContent *);
 
+/* Donne l'origine d'un contenu binaire. */
+static GBinContent *g_file_content_get_root(GFileContent *);
+
 /* Fournit le nom associé au contenu binaire. */
 static const char *g_file_content_describe(const GFileContent *, bool);
 
@@ -181,6 +184,8 @@ static void g_file_content_init(GFileContent *content)
 
 static void g_file_content_interface_init(GBinContentInterface *iface)
 {
+    iface->get_root = (get_content_root_fc)g_file_content_get_root;
+
     iface->describe = (describe_content_fc)g_file_content_describe;
 
     iface->save = (save_content_fc)g_file_content_save;
@@ -376,6 +381,29 @@ GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à consulter.                       *
+*                                                                             *
+*  Description : Donne l'origine d'un contenu binaire.                        *
+*                                                                             *
+*  Retour      : Contenu à l'origine du contenu courant.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinContent *g_file_content_get_root(GFileContent *content)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+
+    result = G_BIN_CONTENT(content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
 *                full    = précise s'il s'agit d'une version longue ou non.   *
 *                                                                             *
 *  Description : Fournit le nom associé au contenu binaire.                   *
diff --git a/src/analysis/contents/memory.c b/src/analysis/contents/memory.c
index a7bdbea..beefe89 100644
--- a/src/analysis/contents/memory.c
+++ b/src/analysis/contents/memory.c
@@ -73,6 +73,9 @@ static void g_memory_content_dispose(GMemoryContent *);
 /* Procède à la libération totale de la mémoire. */
 static void g_memory_content_finalize(GMemoryContent *);
 
+/* Donne l'origine d'un contenu binaire. */
+static GBinContent *g_memory_content_get_root(GMemoryContent *);
+
 /* Fournit le nom associé au contenu binaire. */
 static const char *g_memory_content_describe(const GMemoryContent *, bool);
 
@@ -183,6 +186,8 @@ static void g_memory_content_init(GMemoryContent *content)
 
 static void g_memory_content_interface_init(GBinContentInterface *iface)
 {
+    iface->get_root = (get_content_root_fc)g_memory_content_get_root;
+
     iface->describe = (describe_content_fc)g_memory_content_describe;
 
     iface->save = (save_content_fc)g_memory_content_save;
@@ -357,6 +362,29 @@ GBinContent *g_memory_content_new_from_xml(xmlXPathContextPtr context, const cha
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à consulter.                       *
+*                                                                             *
+*  Description : Donne l'origine d'un contenu binaire.                        *
+*                                                                             *
+*  Retour      : Contenu à l'origine du contenu courant.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinContent *g_memory_content_get_root(GMemoryContent *content)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+
+    result = G_BIN_CONTENT(content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
 *                full    = précise s'il s'agit d'une version longue ou non.   *
 *                                                                             *
 *  Description : Fournit le nom associé au contenu binaire.                   *
diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c
index 711f963..d52e1c0 100644
--- a/src/analysis/contents/restricted.c
+++ b/src/analysis/contents/restricted.c
@@ -66,6 +66,9 @@ static void g_restricted_content_dispose(GRestrictedContent *);
 /* Procède à la libération totale de la mémoire. */
 static void g_restricted_content_finalize(GRestrictedContent *);
 
+/* Donne l'origine d'un contenu binaire. */
+static GBinContent *g_restricted_content_get_root(GRestrictedContent *);
+
 /* Calcule une empreinte unique (SHA256) pour les données. */
 static void g_restricted_content_compute_checksum(GRestrictedContent *, GChecksum *);
 
@@ -168,6 +171,8 @@ static void g_restricted_content_init(GRestrictedContent *content)
 
 static void g_restricted_content_interface_init(GBinContentInterface *iface)
 {
+    iface->get_root = (get_content_root_fc)g_restricted_content_get_root;
+
     iface->compute_checksum = (compute_checksum_fc)g_restricted_content_compute_checksum;
 
     iface->compute_size = (compute_size_fc)g_restricted_content_compute_size;
@@ -290,6 +295,29 @@ GBinContent *g_restricted_content_new_ro(const GBinContent *content, const mrang
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
+*                                                                             *
+*  Description : Donne l'origine d'un contenu binaire.                        *
+*                                                                             *
+*  Retour      : Contenu à l'origine du contenu courant.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinContent *g_restricted_content_get_root(GRestrictedContent *content)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+
+    result = g_binary_content_get_root(content->internal);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content  = contenu binaire à venir lire.                     *
 *                checksum = empreinte de zone mémoire à compléter.            *
 *                                                                             *
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 6c63b0b..dded65b 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -33,13 +33,10 @@
 
 
 #include "fetch.h"
-#include "output.h"
-
 #include "instructions.h"
+#include "output.h"
 #include "routines.h"
 #include "../../core/global.h"
-#include "../../format/format.h"
-#include "../../glibext/delayed-int.h"
 #include "../../glibext/generators/prologue.h"
 #include "../../plugins/pglist.h"
 
@@ -49,190 +46,18 @@
 
 
 
-/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
-
-
-/* Ensembles binaires à désassembler (instance) */
-struct _GDelayedDisassembly
-{
-    GDelayedWork parent;                    /* A laisser en premier        */
-
-    GLoadedBinary *binary;                  /* Destinataire final          */
-    GExeFormat *format;                     /* Format du binaire représenté*/
-    GCodingLanguage *lang;                  /* Traduction en ASM préférée  */
-
-    GBufferCache *cache;                    /* Tampon pour le rendu        */
-
-};
-
-/* Ensembles binaires à désassembler (classe) */
-struct _GDelayedDisassemblyClass
-{
-    GDelayedWorkClass parent;               /* A laisser en premier        */
-
-};
-
-
-/* Initialise la classe des tâches de désassemblage différé. */
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *);
-
-/* Initialise une tâche de désassemblage différé. */
-static void g_delayed_disassembly_init(GDelayedDisassembly *);
-
-/* Supprime toutes les références externes. */
-static void g_delayed_disassembly_dispose(GDelayedDisassembly *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_delayed_disassembly_finalize(GDelayedDisassembly *);
-
-/* Crée une tâche de désassemblage différé. */
-static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GBufferCache *);
-
 /* Opère sur toutes les instructions. */
 static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *);
 
 /* Opère sur toutes les routines. */
 static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GBinFormat *);
 
-/* Assure le désassemblage en différé. */
-static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkStatusStack *);
-
-
-
-/* -------------------------- GESTION GLOBALE DE PROCEDURE -------------------------- */
-
-
-/* Construit la description d'introduction du désassemblage. */
-static void build_disass_prologue(GBufferCache *, const GBinFormat *, const GCodingLanguage *, const char *, const char *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                          DESASSEMBLAGE DE BINAIRE DIFFERE                          */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les tâches de désassemblage différé. */
-G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe des tâches de désassemblage différé.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GDelayedWorkClass *work;                /* Version en classe parente   */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_disassembly_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_delayed_disassembly_finalize;
-
-    work = G_DELAYED_WORK_CLASS(klass);
-
-    work->run = (run_task_fc)g_delayed_disassembly_process;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : disass = instance à initialiser.                             *
-*                                                                             *
-*  Description : Initialise une tâche de désassemblage différé.               *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_delayed_disassembly_init(GDelayedDisassembly *disass)
-{
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : disass = instance d'objet GLib à traiter.                    *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_delayed_disassembly_dispose(GDelayedDisassembly *disass)
-{
-    g_object_unref(G_OBJECT(disass->format));
-    g_object_unref(G_OBJECT(disass->lang));
-
-    G_OBJECT_CLASS(g_delayed_disassembly_parent_class)->dispose(G_OBJECT(disass));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : disass = instance d'objet GLib à traiter.                    *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+/* Réalise un désassemblage effectif. */
+static void compute_disassembly(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *);
 
-static void g_delayed_disassembly_finalize(GDelayedDisassembly *disass)
-{
-    G_OBJECT_CLASS(g_delayed_disassembly_parent_class)->finalize(G_OBJECT(disass));
+/* Imprime le résultat d'un désassemblage. */
+static void output_disassembly(GLoadedBinary *, GProcContext *, GtkStatusStack *, GBufferCache **);
 
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary = binaire chargé en attente des résultats.            *
-*                format = format du binaire représenté.                       *
-*                buffer = tampon de sortie pour les instructions.             *
-*                                                                             *
-*  Description : Crée une tâche de désassemblage différé.                     *
-*                                                                             *
-*  Retour      : Tâche créée.                                                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GBufferCache *cache)
-{
-    GDelayedDisassembly *result;            /* Tâche à retourner           */
-
-    result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL);
-
-    result->binary = binary;
-    result->format = g_loaded_binary_get_format(binary);
-    result->lang = g_asm_language_new();
-
-    result->cache = cache;
-
-    return result;
-
-}
 
 
 /******************************************************************************
@@ -374,10 +199,12 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : disass = analyse à mener.                                    *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : binary  = représentation de binaire chargé.                  *
+*                context = contexte de désassemblage utilisé.                 *
+*                gid     = groupe de travail dédié.                           *
+*                status  = barre de statut à tenir informée.                  *
 *                                                                             *
-*  Description : Assure le désassemblage en différé.                          *
+*  Description : Réalise un désassemblage effectif.                           *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -385,249 +212,100 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatusStack *status)
+static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wgroup_id_t gid, GtkStatusStack *status)
 {
-    wgroup_id_t gid;                        /* Identifiant pour les tâches */
-
-    //GBinFormat *format;                     /* Format du fichier binaire   */
     GArchProcessor *proc;                   /* Architecture du binaire     */
-    GProcContext *ctx;                      /* Contexte de suivi dédié     */
-
-    //size_t i;                               /* Boucle de parcours          */
-
+    GExeFormat *format;                     /* Format du binaire représenté*/
     GArchInstruction **instrs;              /* Instructions résultantes    */
     size_t count;                           /* Quantité de ces instructions*/
 
+    /**
+     * Récupération des objets utiles.
+     */
 
+    proc = g_loaded_binary_get_processor(binary);
 
-    proc = g_loaded_binary_get_processor(disass->binary);
-    ctx = g_arch_processor_get_context(proc);
-
-
-
-    gid = g_work_queue_define_work_group(get_work_queue());
-
-
-
-
-
-
-    /* Première étape */
-
-    //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true);
-
-
-
-    process_disassembly_event(PGA_DISASSEMBLY_STARTED, disass->binary);
-
-
+    format = g_loaded_binary_get_format(binary);
 
-    instrs = disassemble_binary_content(disass->binary, ctx, gid, status, &count);
+    /**
+     * Première étape : collecte des instructions.
+     */
 
+    instrs = disassemble_binary_content(binary, context, gid, status, &count);
 
     g_arch_processor_set_instructions(proc, instrs, count);
 
+    process_disassembly_event(PGA_DISASSEMBLY_RAW, binary);
 
-    // plugins //////////////////////////
-    process_disassembly_event(PGA_DISASSEMBLY_RAW, disass->binary);
-
-
+    /**
+     * Seconde étape : liaisons des instructions.
+     */
 
     process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."),
                              g_instructions_study_do_link_operation,
-                             proc, ctx, disass->format);
-
-
-    // plugins //////////////////////////
-    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, disass->binary);
-
-
-
-    //gtk_extended_status_bar_remove(statusbar, id);
-
+                             proc, context, format);
 
-    //run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true);
+    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, binary);
 
+    /**
+     * Troisième étape : exécution d'éventuels post-traitements.
+     */
 
     process_all_instructions(gid, status, _("Calling 'post' hook on all instructions..."),
                              g_instructions_study_do_post_operation,
-                             proc, ctx, disass->format);
-
-
-
-    // plugins //////////////////////////
-    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_POST, disass->binary);
-
+                             proc, context, format);
 
+    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_POST, binary);
 
     /**
-     * TODO : établir les couvertures de fonctions,
-     * pour être en mesure de disposer de résolution de type XXX+yyy lors
-     * de l'établissement des liens.
+     * Quatrième étape : établissement des couvertures de routines restantes.
      */
 
-
-    /* Seconde étape */
-
-
-
-
     process_all_routines(gid, status,
                          _("Finding remaining limits..."),
-                         g_routines_study_compute_limits, proc, G_BIN_FORMAT(disass->format));
-
-
-
-    // plugins //////////////////////////
-    process_disassembly_event(PGA_DISASSEMBLY_LIMITED, disass->binary);
+                         g_routines_study_compute_limits, proc, G_BIN_FORMAT(format));
 
+    process_disassembly_event(PGA_DISASSEMBLY_LIMITED, binary);
 
-
-    /* Troisième étape */
+    /**
+     * Cinquième étape : liaisons entre instructions.
+     */
 
     process_all_instructions(gid, status, _("Establishing links betweek all instructions..."),
                              g_instructions_study_establish_links,
-                             proc, ctx, disass->format);
-
-
-
-    // plugins //////////////////////////
-    process_disassembly_event(PGA_DISASSEMBLY_LINKED, disass->binary);
-
-
-
-
-
-    /* Quatrième étape */
-
-    // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Detecting loops..."), true);
-
-    // -- old -- detect_loops_in_code(proc, routines, routines_count, statusbar, 0/*id*/);
-
-    // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
-    ///
+                             proc, context, format);
 
-    // plugins //////////////////////////
-    // -- old -- process_disassembly_event(PGA_DISASSEMBLY_LOOPS, disass->binary);
+    process_disassembly_event(PGA_DISASSEMBLY_LINKED, binary);
 
+    /**
+     * Sixième étape : regroupement en blocs basiques.
+     */
 
-
-
-
-
-
-
-
-
-    //////////////////////////////////////
-
-
-    // Control-flow analysis...
-
-#if 1
     process_all_routines(gid, status,
                          _("Control-flow analysis for routines..."),
-                         g_routines_study_handle_blocks, proc, G_BIN_FORMAT(disass->format));
-#endif
-
-
-
-
-    /* Cinquième étape */
-
-    // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Grouping routines instructions..."), true);
-
-    //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
+                         g_routines_study_handle_blocks, proc, G_BIN_FORMAT(format));
 
-    // -- old -- group_routines_instructions(proc, routines, routines_count, statusbar, 0/*id*/);
+    process_disassembly_event(PGA_DISASSEMBLY_GROUPED, binary);
 
-    // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
-    //run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true);
-
-
-    // -- old -- process_disassembly_event(PGA_DISASSEMBLY_GROUPED, disass->binary);
-
-
-
-
-
-    /* Sixième étape */
-
-    // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Ranking each instructions block..."), true);
-
-    //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
-
-    // -- old -- rank_routines_blocks(routines, routines_count, statusbar, 0/*id*/);
-
-    // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
-    //run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true);
-
-
-    // -- old -- process_disassembly_event(PGA_DISASSEMBLY_RANKED, disass->binary);
-
-
-
-    /* Septième étape */
-
-    //id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
-
-
-
-
-    print_disassembled_instructions(disass->cache, disass->lang, disass->binary, G_PRELOAD_INFO(ctx), status);
-
-
-
-
-    /* Rajout de tous les éléments mis en place automatiquement */
-
-    void add_to_collection(GDbItem *item, GLoadedBinary *binary)
-    {
-        g_object_ref(G_OBJECT(item));
-
-        g_loaded_binary_add_to_collection(binary, item);
-
-    }
-
-    g_proc_context_foreach_db_item(ctx, (GFunc)add_to_collection, disass->binary);
-
-    /* Nettoyage final et sortie ! */
+    /**
+     * Nettoyage final et sortie !
+     */
 
-    g_object_unref(G_OBJECT(ctx));
+    g_object_unref(G_OBJECT(format));
 
     g_object_unref(G_OBJECT(proc));
 
-    process_disassembly_event(PGA_DISASSEMBLY_ENDED, disass->binary);
-
-
-
-    //gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
-    //run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED, true);
-
-
-
 }
 
 
-
-/* ---------------------------------------------------------------------------------- */
-/*                            GESTION GLOBALE DE PROCEDURE                            */
-/* ---------------------------------------------------------------------------------- */
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cache    = tampon de destination pour le texte.              *
-*                format   = format associé au contenu représenté.             *
-*                lang     = trauducteur pour l'impression finale.             *
-*                filename = nom du fichier ciblé à décompiler.                *
-*                checksum = empreinte identifiant le binaire chargé.          *
+*  Paramètres  : binary  = représentation de binaire chargé.                  *
+*                context = contexte de désassemblage utilisé.                 *
+*                status  = barre de statut à tenir informée.                  *
+*                cache   = tampon de code mis en place. [OUT]                 *
 *                                                                             *
-*  Description : Construit la description d'introduction du désassemblage.    *
+*  Description : Imprime le résultat d'un désassemblage.                      *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -635,31 +313,82 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 *                                                                             *
 ******************************************************************************/
 
-static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format, const GCodingLanguage *lang, const char *filename, const char *checksum)
+static void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusStack *status, GBufferCache **cache)
 {
+    GBinFormat *format;                     /* Format associé au binaire   */
+    GBinContent *content;                   /* Contenu bianire manipulé    */
+    GCodingLanguage *lang;                  /* Langage de sortie préféré   */
     char **text;                            /* Contenu brute à imprimer    */
+    const char *desc;                       /* Désignation du binaire      */
+    const gchar *checksum;                  /* Identifiant de binaire      */
     GIntroGenerator *generator;             /* Générateur constitué        */
 
+    /**
+     * Initialisation des biens communs.
+     */
+
+    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+    content = g_binary_format_get_content(format);
+    lang = g_asm_language_new();
+
+    *cache = g_buffer_cache_new(content);
+
+    /**
+     * Impression du prologue.
+     */
+
     text = calloc(4, sizeof(char *));
 
     /* Introduction */
 
     text[0] = strdup(_("Disassembly generated by Chrysalide"));
-    text[1] = strdup(_("Chrysalide is free software - © 2008-2016 Cyrille Bagard"));
+    text[1] = strdup(_("Chrysalide is free software - © 2008-2018 Cyrille Bagard"));
 
     /* Fichier */
 
-    asprintf(&text[2], "%s%s", _("File: "), filename);
+    desc = g_binary_content_describe(content, true);
+
+    asprintf(&text[2], "%s%s", _("Source: "), desc);
 
     /* Checksum SHA256 */
 
+    checksum = g_binary_content_get_checksum(content);
+
     asprintf(&text[3], "%s%s", _("Sha256: "), checksum);
 
     /* Intégration finale */
 
     generator = g_intro_generator_new(format, lang, text, 4);
 
-    g_buffer_cache_append(cache, G_LINE_GENERATOR(generator), BLF_NONE);
+    g_buffer_cache_append(*cache, G_LINE_GENERATOR(generator), BLF_NONE);
+
+    /**
+     * Impression des instructions désassemblées.
+     */
+
+    print_disassembled_instructions(*cache, lang, binary, G_PRELOAD_INFO(context), status);
+
+    /**
+     * Rajout de tous les éléments mis en place automatiquement.
+     */
+
+    void add_to_collection(GDbItem *item, gpointer unused)
+    {
+        g_object_ref(G_OBJECT(item));
+
+        g_loaded_binary_add_to_collection(binary, item);
+
+    }
+
+    g_proc_context_foreach_db_item(context, (GFunc)add_to_collection, NULL);
+
+    /**
+     * Nettoyage avant sortie.
+     */
+
+    g_object_unref(G_OBJECT(lang));
+    g_object_unref(G_OBJECT(content));
+    g_object_unref(G_OBJECT(format));
 
 }
 
@@ -667,11 +396,9 @@ static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format,
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = représentation de binaire chargé.                   *
-*                parts  = parties binaires à désassembler.                    *
-*                count  = nombre de parties à traiter.                        *
-*                instrs = liste des instructions chargées. [OUT]              *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
 *                cache  = tampon de code mis en place. [OUT]                  *
-*                ack    = fonction à appeler une fois l'opération terminée.   *
 *                                                                             *
 *  Description : Procède au désassemblage d'un contenu binaire donné.         *
 *                                                                             *
@@ -681,38 +408,31 @@ static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format,
 *                                                                             *
 ******************************************************************************/
 
-void disassemble_binary(GLoadedBinary *binary, GBufferCache **cache, disassembly_ack_fc ack)
+void disassemble_binary(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status, GBufferCache **cache)
 {
-    GBinFormat *format;                     /* Format associé au binaire   */
-    GBinContent *content;                   /* Contenu bianire manipulé    */
-    GCodingLanguage *lang;                  /* Langage de sortie préféré   */
-    const char *desc;                       /* Désignation du binaire      */
-    const gchar *checksum;                  /* Identifiant de binaire      */
-    GDelayedDisassembly *disass;            /* Désassemblage à mener       */
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    GProcContext *context;                  /* Contexte de suivi dédié     */
 
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-    content = g_binary_format_get_content(format);
+    /* Préparatifs */
 
-    *cache = g_buffer_cache_new(content);
+    process_disassembly_event(PGA_DISASSEMBLY_STARTED, binary);
 
-    lang = g_asm_language_new();
+    proc = g_loaded_binary_get_processor(binary);
 
-    desc = g_binary_content_describe(content, true);
-    checksum = g_binary_content_get_checksum(content);
+    context = g_arch_processor_get_context(proc);
 
-    build_disass_prologue(*cache, format, lang, desc, checksum);
+    /* Lancement des opérations ! */
 
-    g_object_unref(G_OBJECT(lang));
-    g_object_unref(G_OBJECT(content));
-    g_object_unref(G_OBJECT(format));
+    compute_disassembly(binary, context, gid, status);
 
-    disass = g_delayed_disassembly_new(binary, *cache);
+    process_disassembly_event(PGA_DISASSEMBLY_ENDED, binary);
 
-    if (ack != NULL)
-        g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary);
+    output_disassembly(binary, context, status, cache);
 
-    queue = get_work_queue();
-    g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass), DEFAULT_WORK_GROUP);
+    /* Nettoyage final et sortie ! */
+
+    g_object_unref(G_OBJECT(context));
+
+    g_object_unref(G_OBJECT(proc));
 
 }
diff --git a/src/analysis/disass/disassembler.h b/src/analysis/disass/disassembler.h
index a3fb74f..1adc9a1 100644
--- a/src/analysis/disass/disassembler.h
+++ b/src/analysis/disass/disassembler.h
@@ -26,40 +26,12 @@
 
 
 #include "../binary.h"
+#include "../../glibext/delayed.h"
 
 
 
-/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
-
-
-#define G_TYPE_DELAYED_DISASSEMBLY               g_delayed_disassembly_get_type()
-#define G_DELAYED_DISASSEMBLY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_disassembly_get_type(), GDelayedDisassembly))
-#define G_IS_DELAYED_DISASSEMBLY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_disassembly_get_type()))
-#define G_DELAYED_DISASSEMBLY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
-#define G_IS_DELAYED_DISASSEMBLY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_DISASSEMBLY))
-#define G_DELAYED_DISASSEMBLY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
-
-
-/* Ensembles binaires à désassembler (instance) */
-typedef struct _GDelayedDisassembly GDelayedDisassembly;
-
-/* Ensembles binaires à désassembler (classe) */
-typedef struct _GDelayedDisassemblyClass GDelayedDisassemblyClass;
-
-
-/* Indique le type défini pour les tâches de désassemblage différé. */
-GType g_delayed_disassembly_get_type(void);
-
-
-
-/* -------------------------- GESTION GLOBALE DE PROCEDURE -------------------------- */
-
-
-/* Acquitte la fin d'un désasemblage différé et complet. */
-typedef void (* disassembly_ack_fc) (GDelayedDisassembly *, GLoadedBinary *);
-
-/* Procède à la décompilation des routines d'un fichier donné. */
-void disassemble_binary(GLoadedBinary *, GBufferCache **, disassembly_ack_fc);
+/* Procède au désassemblage d'un contenu binaire donné. */
+void disassemble_binary(GLoadedBinary *, wgroup_id_t, GtkStatusStack *, GBufferCache **);
 
 
 
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 55afe5a..934c755 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -395,7 +395,7 @@ static bool check_if_extra_wait_is_needed(GWorkQueue *queue, wgroup_id_t id, GPr
 
 GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status, size_t *count)
 {
-    GArchInstruction **result;               /* Instruction désassemblées   */
+    GArchInstruction **result;              /* Instruction désassemblées   */
     GDelayedFetching template;              /* Patron des tâches à venir   */
     GBinFormat *format;                     /* Format du fichier binaire   */
     GBinContent *content;                   /* Contenu binaire à manipuler */
diff --git a/src/analysis/loaded-int.h b/src/analysis/loaded-int.h
index 60d7304..7d4bb19 100644
--- a/src/analysis/loaded-int.h
+++ b/src/analysis/loaded-int.h
@@ -26,9 +26,25 @@
 
 
 #include "loaded.h"
+#include "../glibext/delayed-int.h"
 
 
 
+/* Interprète un contenu chargé avec un appui XML. */
+typedef bool (* restore_content_fc) (GLoadedContent *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Ecrit une sauvegarde de l'élément dans un fichier XML. */
+typedef bool (* save_content_fc) (const GLoadedContent *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Fournit le contenu représenté de l'élément chargé. */
+typedef GBinContent * (* get_content_fc) (const GLoadedContent *);
+
+/* Fournit le format associé à l'élément chargé. */
+typedef const char * (* get_format_name_fc) (const GLoadedContent *);
+
+/* Assure l'analyse d'un contenu chargé en différé. */
+typedef bool (* analyze_loaded_fc) (GLoadedContent *, wgroup_id_t, GtkStatusStack *);
+
 /* Fournit le désignation associée à l'élément chargé. */
 typedef const char * (* describe_loaded_fc) (const GLoadedContent *, bool);
 
@@ -55,6 +71,14 @@ struct _GLoadedContentIface
 
     /* Méthodes virtuelles */
 
+    restore_content_fc restore;             /* Restauration depuis du XML  */
+    save_content_fc save;                   /* Sauvegarde dans du XML      */
+
+    get_content_fc get_content;             /* Fourniture du contenu brut  */
+    get_format_name_fc get_format_name;     /* Fourniture du format associé*/
+
+    analyze_loaded_fc analyze;              /* Analyse du contenu chargé   */
+
     describe_loaded_fc describe;            /* Description de contenu      */
 
     count_loaded_views_fc count_views;      /* Compteur de vues            */
@@ -66,6 +90,8 @@ struct _GLoadedContentIface
 
     /* Signaux */
 
+    void (* analyzed) (GLoadedContent *, gboolean);
+
     void (* display_changed) (GLoadedContent *, unsigned int, unsigned int);
 
 };
diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c
index 450784b..1273ebd 100644
--- a/src/analysis/loaded.c
+++ b/src/analysis/loaded.c
@@ -28,17 +28,79 @@
 
 
 #include "loaded-int.h"
+#include "../core/global.h"
 #include "../glibext/chrysamarshal.h"
 #include "../glibext/gloadedpanel.h"
 
 
 
+/* Analyse de contenu chargé (instance) */
+typedef struct _GLoadedAnalysis GLoadedAnalysis;
+
+
+
 /* ---------------------- GESTION SOUS FORME DE CONTENU CHARGE ---------------------- */
 
 
 /* Procède à l'initialisation de l'interface de contenu chargé. */
 static void g_loaded_content_default_init(GLoadedContentInterface *);
 
+/* Acquitte la fin d'une tâche d'analyse différée et complète. */
+static void on_loaded_content_analysis_completed(GLoadedAnalysis *, GLoadedContent *);
+
+
+
+/* -------------------------- PHASE D'ANALYSE EN PARALLELE -------------------------- */
+
+
+#define G_TYPE_LOADED_ANALYSIS            g_loaded_analysis_get_type()
+#define G_LOADED_ANALYSIS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LOADED_ANALYSIS, GDelayedDisassembly))
+#define G_IS_LOADED_ANALYSIS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LOADED_ANALYSIS))
+#define G_LOADED_ANALYSIS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOADED_ANALYSIS, GDelayedDisassemblyClass))
+#define G_IS_LOADED_ANALYSIS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOADED_ANALYSIS))
+#define G_LOADED_ANALYSIS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOADED_ANALYSIS, GDelayedDisassemblyClass))
+
+
+/* Analyse de contenu chargé (instance) */
+struct _GLoadedAnalysis
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    GLoadedContent *content;                /* Cible de l'analyse à mener  */
+
+    bool success;                           /* Bilan de l'opération        */
+
+};
+
+/* Analyse de contenu chargé (classe) */
+typedef struct _GLoadedAnalysisClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+} GLoadedAnalysisClass;
+
+
+/* Indique le type défini pour les tâches d'analyse différée. */
+static GType g_loaded_analysis_get_type(void);
+
+/* Initialise la classe des tâches d'analyse différées. */
+static void g_loaded_analysis_class_init(GLoadedAnalysisClass *);
+
+/* Initialise une tâche d'analyse de contenu différée. */
+static void g_loaded_analysis_init(GLoadedAnalysis *);
+
+/* Supprime toutes les références externes. */
+static void g_loaded_analysis_dispose(GLoadedAnalysis *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_loaded_analysis_finalize(GLoadedAnalysis *);
+
+/* Crée une tâche d'analyse de contenu différée. */
+static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *);
+
+/* Assure l'analyse d'un contenu chargé en différé. */
+static void g_loaded_analysis_process(GLoadedAnalysis *, GtkStatusStack *);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -64,6 +126,14 @@ G_DEFINE_INTERFACE(GLoadedContent, g_loaded_content, G_TYPE_OBJECT)
 
 static void g_loaded_content_default_init(GLoadedContentInterface *iface)
 {
+    g_signal_new("analyzed",
+                 G_TYPE_LOADED_CONTENT,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GLoadedContentIface, analyzed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
     g_signal_new("display-changed",
                  G_TYPE_LOADED_CONTENT,
                  G_SIGNAL_RUN_LAST,
@@ -77,6 +147,205 @@ static void g_loaded_content_default_init(GLoadedContentInterface *iface)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : content = élément chargé à traiter.                          *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé au binaire.                 *
+*                                                                             *
+*  Description : Interprète un contenu chargé avec un appui XML.              *
+*                                                                             *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_loaded_content_restore(GLoadedContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(content);
+
+    result = iface->restore(content, xdoc, context, path);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément chargé à traiter.                          *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé à l'élément.                *
+*                                                                             *
+*  Description : Ecrit une sauvegarde de l'élément dans un fichier XML.       *
+*                                                                             *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_loaded_content_save(const GLoadedContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(content);
+
+    result = iface->save(content, xdoc, context, path);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément chargé à manipuler.                        *
+*                                                                             *
+*  Description : Fournit le contenu représenté de l'élément chargé.           *
+*                                                                             *
+*  Retour      : Contenu représenté.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_loaded_content_get_content(const GLoadedContent *content)
+{
+    GBinContent *result;                    /* Contenu interne à renvoyer  */
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(content);
+
+    result = iface->get_content(content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément chargé à manipuler.                        *
+*                                                                             *
+*  Description : Fournit le format associé à l'élément chargé.                *
+*                                                                             *
+*  Retour      : Format associé à l'élément chargé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_loaded_content_get_format_name(const GLoadedContent *content)
+{
+    const char *result;                     /* Contenu interne à renvoyer  */
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(content);
+
+    result = iface->get_format_name(content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément chargé à manipuler.                        *
+*                                                                             *
+*  Description : Lance l'analyse propre à l'élément chargé.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_loaded_content_analyze(GLoadedContent *content)
+{
+    GLoadedAnalysis *analysis;              /* Analyse à mener             */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+
+    analysis = g_loaded_analysis_new(content);
+
+    g_signal_connect(analysis, "work-completed",
+                     G_CALLBACK(on_loaded_content_analysis_completed), content);
+
+    queue = get_work_queue();
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(analysis), DEFAULT_WORK_GROUP);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : analysis = tâche d'analyse menée à bien.                     *
+*                content  = contenu chargé dont l'analyse est terminée.       *
+*                                                                             *
+*  Description : Acquitte la fin d'une tâche d'analyse différée et complète.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_loaded_content_analysis_completed(GLoadedAnalysis *analysis, GLoadedContent *content)
+{
+    g_signal_emit_by_name(content, "analyzed", analysis->success);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément chargé à manipuler.                        *
+*                                                                             *
+*  Description : Lance l'analyse de l'élément chargé et attend sa conclusion. *
+*                                                                             *
+*  Retour      : Conclusion obtenue suite à l'analyse.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_loaded_content_analyze_and_wait(GLoadedContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+    GLoadedAnalysis *analysis;              /* Analyse à mener             */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+
+    analysis = g_loaded_analysis_new(content);
+    g_object_ref(G_OBJECT(analysis));
+
+    queue = get_work_queue();
+
+    gid = g_work_queue_define_work_group(queue);
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(analysis), gid);
+
+    g_work_queue_wait_for_completion(queue, gid);
+
+    g_work_queue_delete_work_group(queue, gid);
+
+    result = analysis->success;
+    g_object_unref(G_OBJECT(analysis));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content = élément chargé à consulter.                        *
 *                long    = précise s'il s'agit d'une version longue ou non.   *
 *                                                                             *
@@ -243,6 +512,162 @@ void g_loaded_content_set_display_option(GLoadedContent *content, unsigned int i
 
 
 /* ---------------------------------------------------------------------------------- */
+/*                            PHASE D'ANALYSE EN PARALLELE                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches d'analyse différée. */
+G_DEFINE_TYPE(GLoadedAnalysis, g_loaded_analysis, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches d'analyse différées.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_loaded_analysis_class_init(GLoadedAnalysisClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_loaded_analysis_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_loaded_analysis_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_loaded_analysis_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : analysis = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une tâche d'analyse de contenu différée.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_loaded_analysis_init(GLoadedAnalysis *analysis)
+{
+    analysis->success = false;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : disass = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_loaded_analysis_dispose(GLoadedAnalysis *analysis)
+{
+    g_object_unref(G_OBJECT(analysis->content));
+
+    G_OBJECT_CLASS(g_loaded_analysis_parent_class)->dispose(G_OBJECT(analysis));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : analysis = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_loaded_analysis_finalize(GLoadedAnalysis *analysis)
+{
+    G_OBJECT_CLASS(g_loaded_analysis_parent_class)->finalize(G_OBJECT(analysis));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu chargé à traiter.                          *
+*                                                                             *
+*  Description : Crée une tâche d'analyse de contenu différée.                *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *content)
+{
+    GLoadedAnalysis *result;            /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_LOADED_ANALYSIS, NULL);
+
+    result->content = content;
+    g_object_ref(G_OBJECT(content));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : analysis = analyse à mener.                                  *
+*                status   = barre de statut à tenir informée.                 *
+*                                                                             *
+*  Description : Assure l'analyse d'un contenu chargé en différé.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_loaded_analysis_process(GLoadedAnalysis *analysis, GtkStatusStack *status)
+{
+    GLoadedContentIface *iface;             /* Interface utilisée          */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+
+    iface = G_LOADED_CONTENT_GET_IFACE(analysis->content);
+
+    queue = get_work_queue();
+
+    gid = g_work_queue_define_work_group(queue);
+
+    analysis->success = iface->analyze(analysis->content, gid, status);
+
+    g_work_queue_delete_work_group(queue, gid);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
 /*                         VUES ET BASCULEMENT ENTRE LES VUES                         */
 /* ---------------------------------------------------------------------------------- */
 
diff --git a/src/analysis/loaded.h b/src/analysis/loaded.h
index b74a03d..643e170 100644
--- a/src/analysis/loaded.h
+++ b/src/analysis/loaded.h
@@ -30,6 +30,8 @@
 #include <gtk/gtk.h>
 
 
+#include "content.h"
+#include "../common/xml.h"
 #include "../gtkext/gtkdockstation.h"
 
 
@@ -55,6 +57,24 @@ typedef struct _GLoadedContentIface GLoadedContentIface;
 /* Détermine le type d'une interface pour l'intégration de contenu chargé. */
 GType g_loaded_content_get_type(void) G_GNUC_CONST;
 
+/* Interprète un contenu chargé avec un appui XML. */
+bool g_loaded_content_restore(GLoadedContent *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Ecrit une sauvegarde de l'élément dans un fichier XML. */
+bool g_loaded_content_save(const GLoadedContent *, xmlDoc *, xmlXPathContext *, const char *);
+
+/* Fournit le contenu représenté de l'élément chargé. */
+GBinContent *g_loaded_content_get_content(const GLoadedContent *);
+
+/* Fournit le format associé à l'élément chargé. */
+const char *g_loaded_content_get_format_name(const GLoadedContent *);
+
+/* Lance l'analyse propre à l'élément chargé. */
+void g_loaded_content_analyze(GLoadedContent *);
+
+/* Lance l'analyse de l'élément chargé et attend sa conclusion. */
+bool g_loaded_content_analyze_and_wait(GLoadedContent *);
+
 /* Fournit le désignation associée à l'élément chargé. */
 const char *g_loaded_content_describe(const GLoadedContent *, bool);
 
diff --git a/src/analysis/loading.c b/src/analysis/loading.c
index 5aff20f..f2ae882 100644
--- a/src/analysis/loading.c
+++ b/src/analysis/loading.c
@@ -24,134 +24,268 @@
 #include "loading.h"
 
 
-#include "../core/formats.h"
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
 #include "../core/global.h"
-#include "../core/logs.h"
 #include "../glibext/delayed-int.h"
-#include "../glibext/signal.h"
+#include "../plugins/pglist.h"
+
+
 
+/* ------------------------- TACHE D'EXPLORATION DE CONTENU ------------------------- */
 
 
-/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+#define G_TYPE_EXPLORING_WORK            g_exploring_work_get_type()
+#define G_EXPLORING_WORK(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_EXPLORING_WORK, GExploringWork))
+#define G_IS_EXPLORING_WORK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_EXPLORING_WORK))
+#define G_EXPLORING_WORK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_EXPLORING_WORK, GExploringWorkClass))
+#define G_IS_EXPLORING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_EXPLORING_WORK))
+#define G_EXPLORING_WORK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_EXPLORING_WORK, GExploringWorkClass))
 
 
-/* Ensembles binaires à désassembler (instance) */
-struct _GDelayedStudy
+/* Conversion de contenu binaire en contenu chargé (instance) */
+typedef struct _GExploringWork
 {
     GDelayedWork parent;                    /* A laisser en premier        */
 
-    GStudyProject *project;                 /* Projet de rattachement      */
-    GBinContent *content;                   /* Contenu binaire à traiter   */
-    ProjectContentState state;              /* Renseigne le type de contenu*/
+    const gid_t *gid;                       /* Groupe d'appartenance       */
 
-    bool only_preload;                      /* Enregistrement seulement ?  */
+    GBinContent *content;                   /* Contenu brut à disposition  */
 
-};
+} GExploringWork;
 
-/* Ensembles binaires à désassembler (classe) */
-struct _GDelayedStudyClass
+/* Conversion de contenu binaire en contenu chargé (classe) */
+typedef struct _GExploringWorkClass
 {
     GDelayedWorkClass parent;               /* A laisser en premier        */
 
-};
+} GExploringWorkClass;
 
 
-/* Initialise la classe des intégrations de binaires à étudier. */
-static void g_delayed_study_class_init(GDelayedStudyClass *);
+/* Indique le type défini pour l'exploration de contenu binaire. */
+GType g_exploring_work_get_type(void);
 
-/* Initialise une intégration de binaire à étudier. */
-static void g_delayed_study_init(GDelayedStudy *);
+/* Initialise la classe des tâches d'exploration de contenu. */
+static void g_exploring_work_class_init(GExploringWorkClass *);
+
+/* Initialise une tâche d'exploration de contenu. */
+static void g_exploring_work_init(GExploringWork *);
 
 /* Supprime toutes les références externes. */
-static void g_delayed_study_dispose(GDelayedStudy *);
+static void g_exploring_work_dispose(GExploringWork *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_delayed_study_finalize(GDelayedStudy *);
+static void g_exploring_work_finalize(GExploringWork *);
+
+/* Prépare la conversion non bloquée d'un contenu binaire. */
+static GExploringWork *g_exploring_work_new(GBinContent *);
 
-/* Prépare une intégration de binaire au projet courant. */
-static void g_delayed_study_process(GDelayedStudy *, GtkStatusStack *);
+/* Fournit l'identifiant du groupe de rattachement de la tâche. */
+static gid_t g_exploring_work_get_group_id(const GExploringWork *);
 
+/* Définit l'identifiant du groupe de rattachement de la tâche. */
+static void g_exploring_work_set_group_id(GExploringWork *, const gid_t *);
 
+/* Réalise l'exploration effective de formes de contenus. */
+static void g_exploring_work_process(GExploringWork *, GtkStatusStack *);
 
-/* ----------------------- CHARGEMENT DE BINAIRE NON BLOQUANT ----------------------- */
 
 
-#define G_TYPE_BINARY_LOADER            g_binary_loader_get_type()
-#define G_BINARY_LOADER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BINARY_LOADER, GBinaryLoader))
-#define G_IS_BINARY_LOADER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
-#define G_IS_BINARY_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
+/* --------------------- EXPLORATION NON BLOQUANTE DES CONTENUS --------------------- */
 
 
-/* Chargement non bloquant d'un binaire (instance) */
-struct _GBinaryLoader
+/* Regroupement des chargements */
+typedef struct _exploring_group
 {
-    GDelayedWork parent;                    /* A laisser en premier        */
+    GBinContent *original;                  /* Contenu binaire initial     */
 
-    bool from_content;                      /* Sélection de champs         */
+    wgroup_id_t wid;                        /* Groupe de travail           */
+    gid_t gid;                              /* Groupe d'appartenance       */
 
-    union
-    {
-        GBinContent *content;               /* Contenu brut à disposition  */
+    GBinContent **contents;                 /* Contenus reconnus dispos.   */
+    size_t count;                           /* Taille de cette liste       */
+
+} exploring_group;
+
+/* Exploration de contenus binaires (instance) */
+struct _GContentExplorer
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    gid_t generator;                        /* Générateur d'identifiants   */
 
-        struct
-        {
-            char *filename;                 /* Chemin vers l'ensemble XML  */
-            char *path;                     /* Chemin de la définition XML */
+    exploring_group *groups;                /* Rassemblement de chargements*/
+    size_t count;                           /* Nombre de ces groupes       */
+    GMutex mutex;                           /* Accès protégé à la liste    */
 
-        };
+};
 
-    };
+/* Exploration de contenus binaires (classe) */
+struct _GContentExplorerClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
 
-    GStudyProject *project;                 /* Accès aux contenus liés     */
+    /* Signaux */
 
-    GLoadedBinary *binary;                  /* Résultat du chargement      */
+    void (* explored) (GContentExplorer *, gid_t);
 
 };
 
-/* Chargement non bloquant d'un binaire (classe) */
-struct _GBinaryLoaderClass
+
+/* Initialise la classe les explorations de contenus binaires. */
+static void g_content_explorer_class_init(GContentExplorerClass *);
+
+/* Initialise une exploration de contenus binaires. */
+static void g_content_explorer_init(GContentExplorer *);
+
+/* Supprime toutes les références externes. */
+static void g_content_explorer_dispose(GContentExplorer *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_content_explorer_finalize(GContentExplorer *);
+
+/* Retrouve le groupe correspondant à un identifiant donné. */
+static exploring_group *g_content_explorer_find_group(GContentExplorer *, gid_t);
+
+/* Note la fin d'une phase d'exploration de contenu. */
+static void g_content_explorer_ack(GContentExplorer *, GExploringWork *);
+
+
+
+/* ------------------------- TACHE DE RESOLUTION DE CONTENU ------------------------- */
+
+
+#define G_TYPE_RESOLVING_WORK            g_resolving_work_get_type()
+#define G_RESOLVING_WORK(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RESOLVING_WORK, GResolvingWork))
+#define G_IS_RESOLVING_WORK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RESOLVING_WORK))
+#define G_RESOLVING_WORK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RESOLVING_WORK, GResolvingWorkClass))
+#define G_IS_RESOLVING_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RESOLVING_WORK))
+#define G_RESOLVING_WORK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RESOLVING_WORK, GResolvingWorkClass))
+
+
+/* Conversion de contenu binaire en contenu chargé (instance) */
+typedef struct _GResolvingWork
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    const gid_t *gid;                       /* Groupe d'appartenance       */
+
+    GBinContent *content;                   /* Contenu brut à disposition  */
+
+} GResolvingWork;
+
+/* Conversion de contenu binaire en contenu chargé (classe) */
+typedef struct _GResolvingWorkClass
 {
     GDelayedWorkClass parent;               /* A laisser en premier        */
 
+} GResolvingWorkClass;
+
+
+/* Indique le type défini pour la conversion de contenu binaire en contenu chargé. */
+GType g_resolving_work_get_type(void);
+
+/* Initialise la classe des tâches de conversion de contenu. */
+static void g_resolving_work_class_init(GResolvingWorkClass *);
+
+/* Initialise une tâche de conversion de contenu. */
+static void g_resolving_work_init(GResolvingWork *);
+
+/* Supprime toutes les références externes. */
+static void g_resolving_work_dispose(GResolvingWork *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_resolving_work_finalize(GResolvingWork *);
+
+/* Prépare la conversion non bloquée d'un contenu binaire. */
+static GResolvingWork *g_resolving_work_new(GBinContent *);
+
+/* Fournit l'identifiant du groupe de rattachement de la tâche. */
+static gid_t g_resolving_work_get_group_id(const GResolvingWork *);
+
+/* Définit l'identifiant du groupe de rattachement de la tâche. */
+static void g_resolving_work_set_group_id(GResolvingWork *, const gid_t *);
+
+/* Réalise la conversion effective de formes de contenus. */
+static void g_resolving_work_process(GResolvingWork *, GtkStatusStack *);
+
+
+
+/* ------------------- RESOLUTION DE CONTENUS BINAIRES EN CHARGES ------------------- */
+
+
+/* Regroupement des chargements */
+typedef struct _resolving_group
+{
+    size_t remaining;                       /* Nombre de tâches restantes  */
+
+    const gid_t *gid;                       /* Groupe d'appartenance       */
+
+    GLoadedContent **loaded;                /* Contenus reconnus à intégrer*/
+    size_t count;                           /* Taille de cette liste       */
+
+} resolving_group;
+
+/* Résolution de contenus binaires en formats chargés (instance) */
+struct _GContentResolver
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    resolving_group *groups;                /* Rassemblement de chargements*/
+    size_t count;                           /* Nombre de ces groupes       */
+    GMutex mutex;                           /* Accès protégé à la liste    */
+
 };
 
+/* Résolution de contenus binaires en formats chargés (classe) */
+struct _GContentResolverClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    /* Signaux */
 
-/* Indique le type défini pour le chargement non bloquant d'un binaire. */
-GType g_binary_loader_get_type(void);
+    void (* resolved) (GContentResolver *, gid_t);
+
+};
 
-/* Initialise la classe des tâches de chargement non bloquant. */
-static void g_binary_loader_class_init(GBinaryLoaderClass *);
 
-/* Initialise une tâche de chargement non bloquant d'un binaire. */
-static void g_binary_loader_init(GBinaryLoader *);
+/* Initialise la classe des résolutions de contenus binaires. */
+static void g_content_resolver_class_init(GContentResolverClass *);
+
+/* Initialise une résolution de contenus binaires. */
+static void g_content_resolver_init(GContentResolver *);
 
 /* Supprime toutes les références externes. */
-static void g_binary_loader_dispose(GBinaryLoader *);
+static void g_content_resolver_dispose(GContentResolver *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_binary_loader_finalize(GBinaryLoader *);
+static void g_content_resolver_finalize(GContentResolver *);
+
+/* Retrouve le groupe correspondant à un identifiant donné. */
+static resolving_group *g_content_resolver_find_group(GContentResolver *, gid_t);
 
-/* Réalise le chargement effectif d'un binaire. */
-static void g_binary_loader_process(GBinaryLoader *, GtkStatusStack *);
+/* Note la fin d'une phase de resolution de contenu. */
+static void g_content_resolver_ack(GContentResolver *, GResolvingWork *);
 
 
 
 /* ---------------------------------------------------------------------------------- */
-/*                         AMORCE POUR CHARGEMENT DE CONTENUS                         */
+/*                           TACHE D'EXPLORATION DE CONTENU                           */
 /* ---------------------------------------------------------------------------------- */
 
 
-/* Indique le type défini pour les tâches de préparations d'étude. */
-G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
+/* Indique le type défini pour l'exploration de contenu binaire. */
+G_DEFINE_TYPE(GExploringWork, g_exploring_work, G_TYPE_DELAYED_WORK);
 
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : klass = classe à initialiser.                                *
 *                                                                             *
-*  Description : Initialise la classe des intégrations de binaires à étudier. *
+*  Description : Initialise la classe des tâches d'exploration de contenu.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -159,27 +293,28 @@ G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_study_class_init(GDelayedStudyClass *klass)
+static void g_exploring_work_class_init(GExploringWorkClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GDelayedWorkClass *work;                /* Version en classe parente   */
 
     object = G_OBJECT_CLASS(klass);
-    work = G_DELAYED_WORK_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_study_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_delayed_study_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_exploring_work_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_exploring_work_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
 
-    work->run = (run_task_fc)g_delayed_study_process;
+    work->run = (run_task_fc)g_exploring_work_process;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dstudy = instance à initialiser.                             *
+*  Paramètres  : work = instance à initialiser.                               *
 *                                                                             *
-*  Description : Initialise une intégration de binaire à étudier.             *
+*  Description : Initialise une tâche d'exploration de contenu.               *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -187,16 +322,18 @@ static void g_delayed_study_class_init(GDelayedStudyClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_study_init(GDelayedStudy *dstudy)
+static void g_exploring_work_init(GExploringWork *work)
 {
-    dstudy->only_preload = false;
+    work->gid = NULL;
+
+    work->content = NULL;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*  Paramètres  : work = instance d'objet GLib à traiter.                      *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
 *                                                                             *
@@ -206,19 +343,18 @@ static void g_delayed_study_init(GDelayedStudy *dstudy)
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_study_dispose(GDelayedStudy *dstudy)
+static void g_exploring_work_dispose(GExploringWork *work)
 {
-    g_object_unref(G_OBJECT(dstudy->project));
-    g_object_unref(G_OBJECT(dstudy->content));
+    g_object_unref(G_OBJECT(work->content));
 
-    G_OBJECT_CLASS(g_delayed_study_parent_class)->dispose(G_OBJECT(dstudy));
+    G_OBJECT_CLASS(g_exploring_work_parent_class)->dispose(G_OBJECT(work));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*  Paramètres  : work = instance d'objet GLib à traiter.                      *
 *                                                                             *
 *  Description : Procède à la libération totale de la mémoire.                *
 *                                                                             *
@@ -228,40 +364,58 @@ static void g_delayed_study_dispose(GDelayedStudy *dstudy)
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_study_finalize(GDelayedStudy *dstudy)
+static void g_exploring_work_finalize(GExploringWork *work)
 {
-    G_OBJECT_CLASS(g_delayed_study_parent_class)->finalize(G_OBJECT(dstudy));
+    G_OBJECT_CLASS(g_exploring_work_parent_class)->finalize(G_OBJECT(work));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = projet dont le contenu est à compléter.            *
-*                content = contenu binaire chargé à analyser.                 *
-*                state   = état du contenu à conserver.                       *
+*  Paramètres  : content = contenu binaire disponible pour traitements.       *
 *                                                                             *
-*  Description : Crée une tâche d'intégration de contenu binaire.             *
+*  Description : Prépare l'exploration non bloquée d'un contenu binaire.      *
 *                                                                             *
-*  Retour      : Tâche créée.                                                 *
+*  Retour      : Tâche de travail mise en place.                              *
 *                                                                             *
-*  Remarques   : L'appelant perd la propriété du contenu.                     *
+*  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content, ProjectContentState state)
+static GExploringWork *g_exploring_work_new(GBinContent *content)
 {
-    GDelayedStudy *result;            /* Tâche à retourner           */
-
-    result = g_object_new(G_TYPE_DELAYED_STUDY, NULL);
+    GExploringWork *result;            /* Tâche à retourner           */
 
-    g_object_ref(G_OBJECT(project));
-    result->project = project;
+    result = g_object_new(G_TYPE_EXPLORING_WORK, NULL);
 
-    g_object_ref(G_OBJECT(content));
     result->content = content;
+    g_object_ref(G_OBJECT(content));
+
+    return result;
+
+}
 
-    result->state = state;
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance à consulter.                                 *
+*                                                                             *
+*  Description : Fournit l'identifiant du groupe de rattachement de la tâche. *
+*                                                                             *
+*  Retour      : Identifiant d'un même ensemble d'explorations.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gid_t g_exploring_work_get_group_id(const GExploringWork *work)
+{
+    gid_t result;                           /* Identifiant à retourner     */
+
+    assert(work->gid != NULL);
+
+    result = *work->gid;
 
     return result;
 
@@ -270,10 +424,30 @@ GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dstudy = intégration à mener.                                *
+*  Paramètres  : work = instance à compléter.                                 *
+*                gid  = identifiant d'un même ensemble d'explorations.        *
+*                                                                             *
+*  Description : Définit l'identifiant du groupe de rattachement de la tâche. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_exploring_work_set_group_id(GExploringWork *work, const gid_t *gid)
+{
+    work->gid = gid;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work   = encadrement de conversion à mener.                  *
 *                status = barre de statut à tenir informée.                   *
 *                                                                             *
-*  Description : Prépare une intégration de binaire au projet courant.        *
+*  Description : Réalise l'exploration effective de formes de contenus.       *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -281,64 +455,64 @@ GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content,
 *                                                                             *
 ******************************************************************************/
 
-static void g_delayed_study_process(GDelayedStudy *dstudy, GtkStatusStack *status)
+static void g_exploring_work_process(GExploringWork *work, GtkStatusStack *status)
 {
-    FormatMatchStatus mstatus;              /* Statut d'une reconnaissance */
-    char *target;                           /* Sous-traitance requise      */
-    GBinaryLoader *loader;                  /* Dispositif de chargement    */
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    gid_t gid;                              /* Groupe d'appartenance       */
 
-    mstatus = find_matching_format(dstudy->content, NULL, &target);
+    gid = g_exploring_work_get_group_id(work);
 
-    switch (mstatus)
-    {
-        case FMS_MATCHED:
+    handle_binary_content(PGA_CONTENT_EXPLORER, work->content, gid, status);
 
-            if (dstudy->only_preload)
-                g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+}
 
-            else
-            {
-                loader = g_binary_loader_new(dstudy->content, dstudy->project);
 
-                queue = get_work_queue();
-                g_work_queue_schedule_work(queue, G_DELAYED_WORK(loader), DEFAULT_WORK_GROUP);
 
-            }
+/* ---------------------------------------------------------------------------------- */
+/*                       EXPLORATION NON BLOQUANTE DES CONTENUS                       */
+/* ---------------------------------------------------------------------------------- */
 
-            break;
 
-        case FMS_FORWARDED:
-            /**
-             * L'émetteur de ce type de réponse a pour charge de
-             * reprogrammer lui même l'analyse de nouveaux contenus.
-             */
-            log_variadic_message(LMT_PROCESS, _("binary '%s' contains other binaries..."),
-                                 g_binary_content_describe(dstudy->content, true));
+/* Indique le type défini pour l'exploration de contenus binaires. */
+G_DEFINE_TYPE(GContentExplorer, g_content_explorer, G_TYPE_OBJECT);
 
-            if (dstudy->state == PCS_ROOT)
-                g_study_project_add_binary_content(dstudy->project, dstudy->content, PCS_ROOT);
 
-            break;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe les explorations de contenus binaires.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-        default:
-            /**
-             * Les jeux sont faits pour le contenu binaire courant.
-             */
-            log_variadic_message(LMT_PROCESS, _("Unknown binary format for '%s'..."),
-                                 g_binary_content_describe(dstudy->content, true));
-            break;
+static void g_content_explorer_class_init(GContentExplorerClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
 
-    }
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_content_explorer_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_content_explorer_finalize;
+
+    g_signal_new("explored",
+                 G_TYPE_CONTENT_EXPLORER,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GContentExplorerClass, explored),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__UINT,
+                 G_TYPE_NONE, 1, G_TYPE_UINT);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dstudy = tâche d'analyse de contenu pour projet à mener.     *
+*  Paramètres  : explorer = instance à initialiser.                           *
 *                                                                             *
-*  Description : Limite l'étude et l'intégration d'un contenu binaire.        *
+*  Description : Initialise une exploration de contenus binaires.             *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -346,19 +520,23 @@ static void g_delayed_study_process(GDelayedStudy *dstudy, GtkStatusStack *statu
 *                                                                             *
 ******************************************************************************/
 
-void g_delayed_study_preload_only(GDelayedStudy *dstudy)
+static void g_content_explorer_init(GContentExplorer *explorer)
 {
-    dstudy->only_preload = true;
+    explorer->generator = 0;
+
+    explorer->groups = NULL;
+    explorer->count = 0;
+
+    g_mutex_init(&explorer->mutex);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu binaire chargé à analyser.                 *
-*                state   = état du contenu à conserver.                       *
+*  Paramètres  : explorer = instance d'objet GLib à traiter.                  *
 *                                                                             *
-*  Description : Programme l'étude et l'intégration d'un contenu binaire.     *
+*  Description : Supprime toutes les références externes.                     *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -366,28 +544,26 @@ void g_delayed_study_preload_only(GDelayedStudy *dstudy)
 *                                                                             *
 ******************************************************************************/
 
-void qck_study_new_content(GBinContent *content, ProjectContentState state)
+static void g_content_explorer_dispose(GContentExplorer *explorer)
 {
-    GStudyProject *project;                 /* Projet courant              */
-    GDelayedStudy *dstudy;                  /* Etude à conduire            */
-
-    project = get_current_project();
+    while (explorer->count > 0)
+        g_content_explorer_delete_group(explorer, explorer->groups[0].gid);
 
-    dstudy = g_delayed_study_new(project, content, state);
+    if (explorer->groups != NULL)
+        free(explorer->groups);
 
-    g_object_unref(G_OBJECT(project));
+    g_mutex_clear(&explorer->mutex);
 
-    study_new_content(dstudy);
+    G_OBJECT_CLASS(g_content_explorer_parent_class)->dispose(G_OBJECT(explorer));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu binaire chargé à analyser.                 *
-*                state   = état du contenu à conserver.                       *
+*  Paramètres  : explorer = instance d'objet GLib à traiter.                  *
 *                                                                             *
-*  Description : Programme l'étude et l'intégration d'un contenu binaire.     *
+*  Description : Procède à la libération totale de la mémoire.                *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -395,60 +571,73 @@ void qck_study_new_content(GBinContent *content, ProjectContentState state)
 *                                                                             *
 ******************************************************************************/
 
-void study_new_content(GDelayedStudy *dstudy)
+static void g_content_explorer_finalize(GContentExplorer *explorer)
 {
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
-
-    queue = get_work_queue();
-    g_work_queue_schedule_work(queue, G_DELAYED_WORK(dstudy), DEFAULT_WORK_GROUP);
+    G_OBJECT_CLASS(g_content_explorer_parent_class)->finalize(G_OBJECT(explorer));
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un gestionnaire des explorations de contenus binaires.  *
+*                                                                             *
+*  Retour      : Instance mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GContentExplorer *g_content_explorer_new(void)
+{
+    GContentExplorer *result;            /* Tâche à retourner           */
 
-/* ---------------------------------------------------------------------------------- */
-/*                         CHARGEMENT DE BINAIRE NON BLOQUANT                         */
-/* ---------------------------------------------------------------------------------- */
+    result = g_object_new(G_TYPE_CONTENT_EXPLORER, NULL);
 
+    return result;
 
-/* Indique le type défini pour le chargement non bloquant d'un binaire. */
-G_DEFINE_TYPE(GBinaryLoader, g_binary_loader, G_TYPE_DELAYED_WORK);
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
+*  Paramètres  : explorer = gestionnaire d'explorations à consulter.          *
+*                gid      = identifiant du groupe recherché.                  *
 *                                                                             *
-*  Description : Initialise la classe des tâches de chargement non bloquant.  *
+*  Description : Retrouve le groupe correspondant à un identifiant donné.     *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_binary_loader_class_init(GBinaryLoaderClass *klass)
+static exploring_group *g_content_explorer_find_group(GContentExplorer *explorer, gid_t gid)
 {
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GDelayedWorkClass *work;                /* Version en classe parente   */
+    exploring_group *result;            /* Trouvaille à retourner      */
+    size_t i;                           /* Boucle de parcours          */
 
-    object = G_OBJECT_CLASS(klass);
+    assert(!g_mutex_trylock(&explorer->mutex));
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_loader_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_binary_loader_finalize;
+    result = NULL;
 
-    work = G_DELAYED_WORK_CLASS(klass);
+    for (i = 0; i < explorer->count && result == NULL; i++)
+        if (explorer->groups[i].gid == gid)
+            result = &explorer->groups[i];
 
-    work->run = (run_task_fc)g_binary_loader_process;
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loader = instance à initialiser.                             *
+*  Paramètres  : explorer = gestionnaire d'explorations à consulter.          *
+*                work     = exploration qui vient de se terminer.             *
 *                                                                             *
-*  Description : Initialise une tâche de chargement non bloquant d'un binaire.*
+*  Description : Note la fin d'une phase d'exploration de contenu.            *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -456,213 +645,877 @@ static void g_binary_loader_class_init(GBinaryLoaderClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_binary_loader_init(GBinaryLoader *loader)
+static void g_content_explorer_ack(GContentExplorer *explorer, GExploringWork *work)
 {
-    loader->binary = NULL;
+    gid_t gid;                              /* Groupe d'appartenance       */
+    exploring_group *group;                 /* Groupe d'opération concerné */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    bool empty;                             /* Fin de l'exploration ?      */
+
+    gid = g_exploring_work_get_group_id(work);
+
+    g_mutex_lock(&explorer->mutex);
+
+    group = g_content_explorer_find_group(explorer, gid);
+    assert(group != NULL);
+
+    queue = get_work_queue();
+
+    empty = g_work_queue_is_empty(queue, group->wid);
+
+    g_mutex_unlock(&explorer->mutex);
+
+    if (empty)
+        g_signal_emit_by_name(explorer, "explored", gid);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loader = instance d'objet GLib à traiter.                    *
+*  Paramètres  : explorer = gestionnaire d'explorations à manipuler.          *
+*                content  = contenu initial à découvrir.                      *
 *                                                                             *
-*  Description : Supprime toutes les références externes.                     *
+*  Description : Initie une nouvelle vague d'exploration de contenu.          *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Identifiant du nouveau groupe mis en place.                  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_binary_loader_dispose(GBinaryLoader *loader)
+const gid_t *g_content_explorer_create_group(GContentExplorer *explorer, GBinContent *content)
 {
-    if (loader->from_content)
-        g_object_unref(G_OBJECT(loader->content));
+    const gid_t *result;                    /* Identifiant à retourner     */
+    gid_t loop;                             /* Détection de boucle         */
+    gid_t id;                               /* Nouvelle identifiant généré */
+    exploring_group *group;                 /* Groupe ciblé par l'opération*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    GExploringWork *work;                   /* Nouvelle vague d'exploration*/
+
+    g_mutex_lock(&explorer->mutex);
+
+    /* Récupération d'un identifiant libre */
+
+    /**
+     * Note :
+     *
+     * Comme 0 est l'identifiant du groupe de travail par défaut (DEFAULT_WORK_GROUP)
+     * et qu'il n'est pas possible de bloquer ce groupe lors des appels à
+     * g_work_queue_is_empty(), on différencie les identifiants de groupes
+     * de contenus et les identifiants de groupes de travail.
+     */
+
+    loop = explorer->generator;
+
+    do
+    {
+        id = ++explorer->generator;
+
+        /* Verification de la satisfaisabilité de la création */
+
+        assert(id != loop);
+
+        /* Vérification que la place est libre... */
+
+        group = g_content_explorer_find_group(explorer, id);
+
+        if (group == NULL)
+            break;
+
+    }
+    while (1);
+
+    /* Mise en place du groupe */
+
+    explorer->groups = (exploring_group *)realloc(explorer->groups, ++explorer->count * sizeof(exploring_group));
+
+    group = &explorer->groups[explorer->count - 1];
+
+    group->original = content;
+    g_object_ref(G_OBJECT(content));
 
-    g_object_unref(G_OBJECT(loader->project));
+    queue = get_work_queue();
+
+    group->wid = g_work_queue_define_work_group(queue);
+    group->gid = id;
+
+    result = &group->gid;
+
+    group->contents = NULL;
+    group->count = 0;
+
+    /* Alimentation du contenu initial */
+
+    work = g_exploring_work_new(content);
+    g_exploring_work_set_group_id(work, &group->gid);
+
+    g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_explorer_ack), explorer);
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), group->wid);
 
-    if (loader->binary != NULL)
-        g_object_unref(G_OBJECT(loader->binary));
+    g_mutex_unlock(&explorer->mutex);
 
-    G_OBJECT_CLASS(g_binary_loader_parent_class)->dispose(G_OBJECT(loader));
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loader = instance d'objet GLib à traiter.                    *
+*  Paramètres  : explorer = gestionnaire d'explorations à manipuler.          *
+*                gid      = identifiant du groupe à consulter.                *
 *                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
+*  Description : Fournit l'identifiant attribué pour les tâches parallèles.   *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Identifiant des tâches liées au groupe.                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_binary_loader_finalize(GBinaryLoader *loader)
+const wgroup_id_t *g_content_explorer_get_group_work_id(GContentExplorer *explorer, gid_t gid)
 {
-    if (!loader->from_content)
-    {
-        free(loader->filename);
-        free(loader->path);
-    }
+    const wgroup_id_t *result;              /* Identifiant à retourner     */
+    exploring_group *group;                 /* Groupe d'opération concerné */
+
+    g_mutex_lock(&explorer->mutex);
+
+    group = g_content_explorer_find_group(explorer, gid);
+    assert(group != NULL);
+
+    result = &group->wid;
 
-    G_OBJECT_CLASS(g_binary_loader_parent_class)->finalize(G_OBJECT(loader));
+    g_mutex_unlock(&explorer->mutex);
+
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu binaire chargé en mémoire.                 *
-*                project  = projet dans lequel venir ajouter des contenus.    *
+*  Paramètres  : explorer = gestionnaire d'explorations à manipuler.          *
+*                gid      = identifiant du groupe à supprimer.                *
 *                                                                             *
-*  Description : Prépare le chargement non bloqué d'un contenu binaire.       *
+*  Description : Termine une vague d'exploration de contenu.                  *
 *                                                                             *
-*  Retour      : Instance de binaire chargé ou NULL en cas d'échec.           *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GBinaryLoader *g_binary_loader_new(GBinContent *content, GStudyProject *project)
+void g_content_explorer_delete_group(GContentExplorer *explorer, gid_t gid)
 {
-    GBinaryLoader *result;            /* Tâche à retourner           */
 
-    result = g_object_new(G_TYPE_BINARY_LOADER, NULL);
 
-    result->from_content = true;
 
-    result->content = content;
-    g_object_ref(G_OBJECT(content));
+    exploring_group *group;                 /* Groupe ciblé par l'opération*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    size_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Indice des paramètres       */
 
-    result->project = project;
-    g_object_ref(G_OBJECT(project));
+    g_mutex_lock(&explorer->mutex);
 
-    return result;
+    group = g_content_explorer_find_group(explorer, gid);
+
+    /* Supression des contenus chargés */
+
+    queue = get_work_queue();
+
+    g_work_queue_delete_work_group(queue, group->wid);
+
+    for (i = 0; i < group->count; i++)
+        g_object_unref(G_OBJECT(group->contents[i]));
+
+    /* Réorganisation de la liste */
+
+    index = group - explorer->groups;
+
+    if ((index + 1) < explorer->count)
+        memmove(&explorer->groups[index], &explorer->groups[index + 1],
+                (explorer->count - index - 1) * sizeof(exploring_group));
+
+    explorer->groups = (exploring_group *)realloc(explorer->groups,
+                                                  --explorer->count * sizeof(exploring_group));
+
+    /* Sortie */
+
+    g_mutex_unlock(&explorer->mutex);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : filename = chemin d'accès au fichier à charger.              *
-*                path     = chemin d'accès au noeud XML à lire.               *
-*                project  = projet dans lequel venir rechercher les contenus. *
+*  Paramètres  : explorer = gestionnaire d'explorations à consulter.          *
+*                gid      = identifiant du groupe à parcourir.                *
+*                content  = nouveau contenu à intégrer.                       *
 *                                                                             *
-*  Description : Prépare le chargement non bloqué d'un contenu XML.           *
+*  Description : Ajoute un nouveau contenu découvert au crédit d'un groupe.   *
 *                                                                             *
-*  Retour      : Instance de binaire chargé ou NULL en cas d'échec.           *
+*  Retour      : -                                                            *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : La propritété du contenu fourni est cédée.                   *
 *                                                                             *
 ******************************************************************************/
 
-GBinaryLoader *g_binary_loader_new_from_xml(const char *filename, const char *path, GStudyProject *project)
+void g_content_explorer_populate_group(GContentExplorer *explorer, gid_t gid, GBinContent *content)
 {
-    GBinaryLoader *result;            /* Tâche à retourner           */
+    exploring_group *group;                 /* Groupe d'opération concerné */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    GExploringWork *work;                   /* Nouvelle vague d'exploration*/
 
-    result = g_object_new(G_TYPE_BINARY_LOADER, NULL);
+    g_mutex_lock(&explorer->mutex);
 
-    result->from_content = false;
+    group = g_content_explorer_find_group(explorer, gid);
+    assert(group != NULL);
 
-    result->filename = strdup(filename);
-    result->path = strdup(path);
+    /* Conservation du résultat */
 
-    result->project = project;
-    g_object_ref(G_OBJECT(project));
+    group->contents = (GBinContent **)realloc(group->contents, ++group->count * sizeof(GBinContent *));
 
-    return result;
+    group->contents[group->count - 1] = content;
+
+    /* Relancement des explorations */
+
+    work = g_exploring_work_new(content);
+    g_exploring_work_set_group_id(work, &group->gid);
+
+    g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_explorer_ack), explorer);
+
+    queue = get_work_queue();
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), group->wid);
+
+    g_mutex_unlock(&explorer->mutex);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loader = encadrement du chargement à mener.                  *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : explorer = gestionnaire d'explorations à consulter.          *
+*                gid      = identifiant du groupe à parcourir.                *
+*                count    = nombre de contenus binaires retournés. [OUT]      *
 *                                                                             *
-*  Description : Réalise le chargement effectif d'un binaire.                 *
+*  Description : Fournit la liste de tous les contenus disponibles.           *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Liste de contenus binaires enregistrés.                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_binary_loader_process(GBinaryLoader *loader, GtkStatusStack *status)
+GBinContent **g_content_explorer_get_all(GContentExplorer *explorer, gid_t gid, size_t *count)
 {
-    xmlDocPtr xdoc;                         /* Structure XML chargée       */
-    xmlXPathContextPtr context;             /* Contexte pour les XPath     */
-    GLoadedBinary *binary;                  /* Binaire désormais en place  */
+    GBinContent **result;                   /* Trouvailles à retourner      */
+    exploring_group *group;                 /* Groupe d'opération concerné */
+    size_t i;                               /* Boucle de parcours          */
 
-    /* Tentative de chargement de binaire */
+    g_mutex_lock(&explorer->mutex);
 
-    if (loader->from_content)
-        loader->binary = g_loaded_binary_new(loader->content);
+    group = g_content_explorer_find_group(explorer, gid);
+    assert(group != NULL);
 
-    else
-    {
-        if (open_xml_file(loader->filename, &xdoc, &context))
-        {
-            loader->binary = g_loaded_binary_new_from_xml(context, loader->path, loader->project);
+    /* Allocation de la liste finale */
 
-            close_xml_file(xdoc, context);
+    *count = 1 + group->count;
+    result = (GBinContent **)malloc(*count * sizeof(GBinContent *));
 
-        }
+    /* On regarde déjà du côté de la source */
 
-    }
+    result[0] = group->original;
+
+    g_object_ref(G_OBJECT(result[0]));
 
-    /* Poursuites qui peuvent être traitées dans la foulée */
+    /* On parcourt les éventuels contenus encapsulés découverts */
 
-    if (loader->binary != NULL)
+    for (i = 0; i < group->count; i++)
     {
-        /* Si le contenu n'a pas déjà été ajouté au projet au moment du chargement de ce dernier... */
-        if (loader->from_content)
-            g_study_project_add_binary_content(loader->project, loader->content, PCS_ROOT/* FIXME : dstudy->state*/);
+        result[1 + i] = group->contents[i];
 
-        binary = g_binary_loader_get_result(loader);
+        g_object_ref(G_OBJECT(result[i + 1]));
+
+    }
 
-        if (binary != NULL)
-        {
-            g_signal_connect_to_main_swapped(binary, "disassembly-done",
-                                             G_CALLBACK(g_study_project_attach_content), loader->project,
-                                             g_cclosure_marshal_VOID__VOID);
+    g_mutex_unlock(&explorer->mutex);
 
-            g_loaded_binary_analyse(binary);
+    return result;
 
-            g_object_unref(G_OBJECT(binary));
+}
 
-        }
 
-    }
 
-}
+/* ---------------------------------------------------------------------------------- */
+/*                           TACHE DE RESOLUTION DE CONTENU                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour la conversion de contenu binaire en contenu chargé. */
+G_DEFINE_TYPE(GResolvingWork, g_resolving_work, G_TYPE_DELAYED_WORK);
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loader = encadrement du chargement à consulter.              *
+*  Paramètres  : klass = classe à initialiser.                                *
 *                                                                             *
-*  Description : Retourne l'instance du binaire chargé en cas de succès.      *
+*  Description : Initialise la classe des tâches de conversion de contenu.    *
 *                                                                             *
-*  Retour      : Instance mise en place ou NULL.                              *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GLoadedBinary *g_binary_loader_get_result(const GBinaryLoader *loader)
+static void g_resolving_work_class_init(GResolvingWorkClass *klass)
 {
-    GLoadedBinary *result;                  /* Chargement à faire suivre   */
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
 
-    result = loader->binary;
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_resolving_work_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_resolving_work_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_resolving_work_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une tâche de conversion de contenu.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_resolving_work_init(GResolvingWork *work)
+{
+    work->gid = NULL;
+
+    work->content = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_resolving_work_dispose(GResolvingWork *work)
+{
+    g_object_unref(G_OBJECT(work->content));
+
+    G_OBJECT_CLASS(g_resolving_work_parent_class)->dispose(G_OBJECT(work));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_resolving_work_finalize(GResolvingWork *work)
+{
+    G_OBJECT_CLASS(g_resolving_work_parent_class)->finalize(G_OBJECT(work));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire disponible pour traitements.       *
+*                                                                             *
+*  Description : Prépare la conversion non bloquée d'un contenu binaire.      *
+*                                                                             *
+*  Retour      : Tâche de travail mise en place.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GResolvingWork *g_resolving_work_new(GBinContent *content)
+{
+    GResolvingWork *result;            /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_RESOLVING_WORK, NULL);
+
+    result->content = content;
+    g_object_ref(G_OBJECT(content));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance à consulter.                                 *
+*                                                                             *
+*  Description : Fournit l'identifiant du groupe de rattachement de la tâche. *
+*                                                                             *
+*  Retour      : Identifiant d'un même ensemble de conversions.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gid_t g_resolving_work_get_group_id(const GResolvingWork *work)
+{
+    gid_t result;                           /* Identifiant à retourner     */
+
+    assert(work->gid != NULL);
+
+    result = *work->gid;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work = instance à compléter.                                 *
+*                gid  = identifiant d'un même ensemble de conversions.        *
+*                                                                             *
+*  Description : Définit l'identifiant du groupe de rattachement de la tâche. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_resolving_work_set_group_id(GResolvingWork *work, const gid_t *gid)
+{
+    work->gid = gid;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : work   = encadrement de conversion à mener.                  *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Réalise la conversion effective de formes de contenus.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_resolving_work_process(GResolvingWork *work, GtkStatusStack *status)
+{
+    gid_t gid;                              /* Groupe d'appartenance       */
+
+    gid = g_resolving_work_get_group_id(work);
+
+    handle_binary_content(PGA_CONTENT_RESOLVER, work->content, gid, status);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                     RESOLUTION DE CONTENUS BINAIRES EN CHARGES                     */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour la résolution de contenus binaires en formats chargés. */
+G_DEFINE_TYPE(GContentResolver, g_content_resolver, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des résolutions de contenus binaires.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_resolver_class_init(GContentResolverClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_content_resolver_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_content_resolver_finalize;
+
+    g_signal_new("resolved",
+                 G_TYPE_CONTENT_RESOLVER,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GContentResolverClass, resolved),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__UINT,
+                 G_TYPE_NONE, 1, G_TYPE_UINT);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une résolution de contenus binaires.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_resolver_init(GContentResolver *resolver)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_resolver_dispose(GContentResolver *resolver)
+{
+    while (resolver->count > 0)
+        g_content_resolver_delete_group(resolver, *resolver->groups[0].gid);
+
+    if (resolver->groups != NULL)
+        free(resolver->groups);
+
+    g_mutex_clear(&resolver->mutex);
+
+    G_OBJECT_CLASS(g_content_resolver_parent_class)->dispose(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_resolver_finalize(GContentResolver *resolver)
+{
+    G_OBJECT_CLASS(g_content_resolver_parent_class)->finalize(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un gestionnaire des résolutions de contenus binaires.   *
+*                                                                             *
+*  Retour      : Instance mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GContentResolver *g_content_resolver_new(void)
+{
+    GContentResolver *result;            /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_CONTENT_RESOLVER, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de résolutions à consulter.          *
+*                gid      = identifiant du groupe recherché.                  *
+*                                                                             *
+*  Description : Retrouve le groupe correspondant à un identifiant donné.     *
+*                                                                             *
+*  Retour      : Groupe trouvé ou NULL en cas d'échec.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static resolving_group *g_content_resolver_find_group(GContentResolver *resolver, gid_t gid)
+{
+    resolving_group *result;            /* Trouvaille à retourner      */
+    size_t i;                           /* Boucle de parcours          */
+
+    assert(!g_mutex_trylock(&resolver->mutex));
+
+    result = NULL;
+
+    for (i = 0; i < resolver->count && result == NULL; i++)
+        if (*resolver->groups[i].gid == gid)
+            result = &resolver->groups[i];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de résolutions à consulter.          *
+*                work     = resolvation qui vient de se terminer.             *
+*                                                                             *
+*  Description : Note la fin d'une phase de resolution de contenu.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_content_resolver_ack(GContentResolver *resolver, GResolvingWork *work)
+{
+    gid_t gid;                              /* Groupe d'appartenance       */
+    resolving_group *group;                 /* Groupe d'opération concerné */
+    bool empty;                             /* Fin de l'resolvation ?      */
+
+    gid = g_resolving_work_get_group_id(work);
+
+    g_mutex_lock(&resolver->mutex);
+
+    group = g_content_resolver_find_group(resolver, gid);
+    assert(group != NULL);
+
+    assert(group->remaining > 0);
+
+    empty = (--group->remaining == 0);
+
+    g_mutex_unlock(&resolver->mutex);
+
+    if (empty)
+        g_signal_emit_by_name(resolver, "resolved", gid);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de résolutions à manipuler.          *
+*                wid      = identifiant du groupe de tâches réservé.          *
+*                gid      = identifiant unique généré en amont.               *
+*                contents = contenus à analyser.                              *
+*                count    = nombre de ces contenus.                           *
+*                                                                             *
+*  Description : Initie une nouvelle vague de résolution de contenus.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_resolver_create_group(GContentResolver *resolver, const wgroup_id_t *wid, const gid_t *gid, GBinContent **contents, size_t count)
+{
+    resolving_group *group;                 /* Groupe ciblé par l'opération*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    size_t i;                               /* Boucle de parcours          */
+    GResolvingWork *work;                   /* Nouvelle vague de résolution*/
+
+    g_mutex_lock(&resolver->mutex);
+
+    /* Mise en place du groupe */
+
+    resolver->groups = (resolving_group *)realloc(resolver->groups, ++resolver->count * sizeof(resolving_group));
+
+    group = &resolver->groups[resolver->count - 1];
+
+    group->remaining = count;
+
+    group->gid = gid;
+
+    group->loaded = NULL;
+    group->count = 0;
+
+    /* Alimentation du contenu initial */
+
+    queue = get_work_queue();
+
+    for (i = 0; i < count; i++)
+    {
+        work = g_resolving_work_new(contents[i]);
+        g_resolving_work_set_group_id(work, gid);
+
+        g_signal_connect_swapped(work, "work-completed", G_CALLBACK(g_content_resolver_ack), resolver);
+
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(work), *wid);
+
+    }
+
+    g_mutex_unlock(&resolver->mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire d'explorations à manipuler.          *
+*                gid      = identifiant du groupe à supprimer.                *
+*                                                                             *
+*  Description : Termine une vague de résolution de contenu.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_resolver_delete_group(GContentResolver *resolver, gid_t gid)
+{
+    resolving_group *group;                 /* Groupe ciblé par l'opération*/
+    size_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Indice des paramètres       */
+
+    g_mutex_lock(&resolver->mutex);
+
+    group = g_content_resolver_find_group(resolver, gid);
+
+    /* Supression des contenus chargés */
+
+    for (i = 0; i < group->count; i++)
+        g_object_unref(G_OBJECT(group->loaded[i]));
+
+    /* Réorganisation de la liste */
+
+    index = group - resolver->groups;
+
+    if ((index + 1) < resolver->count)
+        memmove(&resolver->groups[index], &resolver->groups[index + 1],
+                (resolver->count - index - 1) * sizeof(resolving_group));
+
+    resolver->groups = (resolving_group *)realloc(resolver->groups,
+                                                  --resolver->count * sizeof(resolving_group));
+
+    /* Sortie */
+
+    g_mutex_unlock(&resolver->mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de résolutions à consulter.          *
+*                gid      = identifiant du groupe recherché.                  *
+*                loaded   = contenu chargé et pouvant être représenté.        *
+*                                                                             *
+*  Description : Intègre un contenu chargé dans les résultats.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_resolver_add_detected(GContentResolver *resolver, gid_t gid, GLoadedContent *loaded)
+{
+    resolving_group *group;                 /* Groupe ciblé par l'opération*/
+
+    g_mutex_lock(&resolver->mutex);
+
+    group = g_content_resolver_find_group(resolver, gid);
+
+    group->loaded = (GLoadedContent **)realloc(group->loaded, ++group->count * sizeof(GLoadedContent *));
+
+    group->loaded[group->count - 1] = loaded;
+
+    g_mutex_unlock(&resolver->mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de resolutions à consulter.          *
+*                gid      = identifiant du groupe à parcourir.                *
+*                count    = nombre de contenus binaires retournés. [OUT]      *
+*                                                                             *
+*  Description : Fournit la liste de tous les contenus chargés valables.      *
+*                                                                             *
+*  Retour      : Liste de contenus chargés enregistrés.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GLoadedContent **g_content_resolver_get_all(GContentResolver *resolver, gid_t gid, size_t *count)
+{
+    GLoadedContent **result;                /* Trouvailles à retourner      */
+    resolving_group *group;                 /* Groupe d'opération concerné */
+    size_t i;                               /* Boucle de parcours          */
+
+    g_mutex_lock(&resolver->mutex);
+
+    group = g_content_resolver_find_group(resolver, gid);
+    assert(group != NULL);
+
+    /* Allocation de la liste finale */
+
+    *count = group->count;
+    result = (GLoadedContent **)malloc(*count * sizeof(GLoadedContent *));
+
+    /* On parcourt les éventuels contenus encapsulés découverts */
+
+    for (i = 0; i < group->count; i++)
+    {
+        result[i] = group->loaded[i];
+
+        g_object_ref(G_OBJECT(result[i]));
+
+    }
 
-    if (result != NULL)
-        g_object_ref(G_OBJECT(result));
+    g_mutex_unlock(&resolver->mutex);
 
     return result;
 
diff --git a/src/analysis/loading.h b/src/analysis/loading.h
index 46b42a1..4755226 100644
--- a/src/analysis/loading.h
+++ b/src/analysis/loading.h
@@ -28,74 +28,88 @@
 #include <glib-object.h>
 
 
-#include "project.h"
+#include "content.h"
+#include "loaded.h"
+#include "../glibext/delayed.h"
 
 
 
-/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+/* --------------------- EXPLORATION NON BLOQUANTE DES CONTENUS --------------------- */
 
 
-#define G_TYPE_DELAYED_STUDY               g_delayed_study_get_type()
-#define G_DELAYED_STUDY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_study_get_type(), GDelayedStudy))
-#define G_IS_DELAYED_STUDY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_study_get_type()))
-#define G_DELAYED_STUDY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_STUDY, GDelayedStudyClass))
-#define G_IS_DELAYED_STUDY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_STUDY))
-#define G_DELAYED_STUDY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_STUDY, GDelayedStudyClass))
+#define G_TYPE_CONTENT_EXPLORER            g_content_explorer_get_type()
+#define G_CONTENT_EXPLORER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CONTENT_EXPLORER, GContentExplorer))
+#define G_IS_CONTENT_EXPLORER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CONTENT_EXPLORER))
+#define G_CONTENT_EXPLORER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CONTENT_EXPLORER, GContentExplorerClass))
+#define G_IS_CONTENT_EXPLORER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CONTENT_EXPLORER))
+#define G_CONTENT_EXPLORER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CONTENT_EXPLORER, GContentExplorerClass))
 
 
-/* Ensembles binaires à désassembler (instance) */
-typedef struct _GDelayedStudy GDelayedStudy;
+/* Exploration de contenus binaires (instance) */
+typedef struct _GContentExplorer GContentExplorer;
 
-/* Ensembles binaires à désassembler (classe) */
-typedef struct _GDelayedStudyClass GDelayedStudyClass;
+/* Exploration de contenus binaires (classe) */
+typedef struct _GContentExplorerClass GContentExplorerClass;
 
 
-/* Indique le type défini pour les tâches de préparations d'étude. */
-GType g_delayed_study_get_type(void);
+/* Indique le type défini pour l'exploration de contenus binaires. */
+GType g_content_explorer_get_type(void);
 
-/* Crée une tâche d'intégration de contenu binaire. */
-GDelayedStudy *g_delayed_study_new(GStudyProject *, GBinContent *, ProjectContentState);
+/* Crée un gestionnaire des explorations de contenus binaires. */
+GContentExplorer *g_content_explorer_new(void);
 
-/* Limite l'étude et l'intégration d'un contenu binaire. */
-void g_delayed_study_preload_only(GDelayedStudy *);
+/* Initie une nouvelle vague d'exploration de contenu. */
+const gid_t *g_content_explorer_create_group(GContentExplorer *, GBinContent *);
 
-/* Programme l'étude et l'intégration d'un contenu binaire. */
-void qck_study_new_content(GBinContent *, ProjectContentState);
+/* Fournit l'identifiant attribué pour les tâches parallèles. */
+const wgroup_id_t *g_content_explorer_get_group_work_id(GContentExplorer *, gid_t);
 
-/* Programme l'étude et l'intégration d'un contenu binaire. */
-void study_new_content(GDelayedStudy *);
+/* Termine une vague d'exploration de contenu. */
+void g_content_explorer_delete_group(GContentExplorer *, gid_t);
 
+/* Ajoute un nouveau contenu découvert au crédit d'un groupe. */
+void g_content_explorer_populate_group(GContentExplorer *, gid_t, GBinContent *);
 
+/* Fournit la liste de tous les contenus disponibles. */
+GBinContent **g_content_explorer_get_all(GContentExplorer *, gid_t, size_t *);
 
-/* ----------------------- CHARGEMENT DE BINAIRE NON BLOQUANT ----------------------- */
 
 
-#define G_TYPE_BINARY_LOADER            g_binary_loader_get_type()
-#define G_BINARY_LOADER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BINARY_LOADER, GBinaryLoader))
-#define G_IS_BINARY_LOADER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
-#define G_IS_BINARY_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_LOADER))
-#define G_BINARY_LOADER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_LOADER, GBinaryLoaderClass))
+/* ------------------- RESOLUTION DE CONTENUS BINAIRES EN CHARGES ------------------- */
 
 
-/* Chargement non bloquant d'un binaire (instance) */
-typedef struct _GBinaryLoader GBinaryLoader;
+#define G_TYPE_CONTENT_RESOLVER            g_content_resolver_get_type()
+#define G_CONTENT_RESOLVER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CONTENT_RESOLVER, GContentResolver))
+#define G_IS_CONTENT_RESOLVER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CONTENT_RESOLVER))
+#define G_CONTENT_RESOLVER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CONTENT_RESOLVER, GContentResolverClass))
+#define G_IS_CONTENT_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CONTENT_RESOLVER))
+#define G_CONTENT_RESOLVER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CONTENT_RESOLVER, GContentResolverClass))
 
-/* Chargement non bloquant d'un binaire (classe) */
-typedef struct _GBinaryLoaderClass GBinaryLoaderClass;
 
+/* Résolution de contenus binaires en formats chargés (instance) */
+typedef struct _GContentResolver GContentResolver;
 
-/* Indique le type défini pour le chargement non bloquant d'un binaire. */
-GType g_binary_loader_get_type(void);
+/* Résolution de contenus binaires en formats chargés (classe) */
+typedef struct _GContentResolverClass GContentResolverClass;
 
-/* Prépare le chargement non bloqué d'un contenu binaire. */
-GBinaryLoader *g_binary_loader_new(GBinContent *, GStudyProject *);
 
-/* Prépare le chargement non bloqué d'un contenu XML. */
-GBinaryLoader *g_binary_loader_new_from_xml(const char *, const char *, GStudyProject *);
+/* Indique le type défini pour la résolution de contenus binaires en formats chargés. */
+GType g_content_resolver_get_type(void);
 
-/* Retourne l'instance du binaire chargé en cas de succès. */
-GLoadedBinary *g_binary_loader_get_result(const GBinaryLoader *);
+/* Crée un gestionnaire des résolutions de contenus binaires. */
+GContentResolver *g_content_resolver_new(void);
+
+/* Initie une nouvelle vague de résolution de contenus. */
+void g_content_resolver_create_group(GContentResolver *, const wgroup_id_t *, const gid_t *, GBinContent **, size_t);
+
+/* Termine une vague de résolution de contenu. */
+void g_content_resolver_delete_group(GContentResolver *, gid_t);
+
+/* Intègre un contenu chargé dans les résultats. */
+void g_content_resolver_add_detected(GContentResolver *, gid_t, GLoadedContent *);
+
+/* Fournit la liste de tous les contenus chargés valables. */
+GLoadedContent **g_content_resolver_get_all(GContentResolver *, gid_t, size_t *);
 
 
 
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 09b4aad..88b468a 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -25,7 +25,6 @@
 
 
 #include <assert.h>
-#include <inttypes.h>
 #include <malloc.h>
 #include <string.h>
 
@@ -33,40 +32,33 @@
 #include <i18n.h>
 
 
-#include "loaded.h"
 #include "loading.h"
 #include "../common/xml.h"
 #include "../core/global.h"
 #include "../core/logs.h"
 #include "../core/params.h"
-#include "../glibext/delayed-int.h"
-#include "../gui/core/panels.h"
-#include "../gui/panels/panel.h"
-#include "../format/format.h"
 
 
 
 /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
 
 
-/* Conservation d'un contenu chargé */
-typedef struct _loaded_content
+/* Suivi du chargement de contenus binaires */
+typedef struct _loading_params
 {
-    GBinContent *content;                   /* Contenu binaire en place    */
-    ProjectContentState state;              /* Renseigne le type de contenu*/
-
-} loaded_content;
-
-/* Conservation d'un binaire chargé */
-typedef struct _loaded_binary
-{
-    GLoadedBinary *binary;                  /* Binaire en question         */
+    union
+    {
+        const gid_t *exp_gid;               /* Identifiant d'exploration   */
+        const gid_t **exp_gids;             /* Identifiants d'exploration  */
+    };
+    size_t exp_count;                       /* Quantitié d'identifiants    */
 
-    GPanelItem **items;                     /* Supports d'affichage final  */
-    size_t count;                           /* Nombre de ces supports      */
+    size_t resolved;                        /* Compteur de résolutions     */
 
-} loaded_binary;
+    xmlDoc *xdoc;                           /* Structure XML chargée ?     */
+    xmlXPathContext *context;               /* Eventuel contexte XML       */
 
+} loading_params;
 
 /* Projet d'étude regroupant les binaires analysés (instance) */
 struct _GStudyProject
@@ -75,6 +67,10 @@ struct _GStudyProject
 
     char *filename;                         /* Lieu d'enregistrement       */
 
+    loading_params *ld_params;              /* Infos d'accompagnement      */
+    size_t ld_count;                        /* Quantité de ces infos       */
+    GMutex ld_mutex;                        /* Encadrement des accès       */
+
     GLoadedContent **contents;              /* Contenus chargés et intégrés*/
     size_t count;                           /* Quantité de ces contenus    */
     GMutex mutex;                           /* Encadrement des accès       */
@@ -101,6 +97,38 @@ static void g_study_project_class_init(GStudyProjectClass *);
 /*Initialise une instance de projet d'étude. */
 static void g_study_project_init(GStudyProject *);
 
+/* Supprime toutes les références externes. */
+static void g_study_project_dispose(GStudyProject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_study_project_finalize(GStudyProject *);
+
+
+
+/* ------------------------ INTEGRATION DE CONTENUS BINAIRES ------------------------ */
+
+
+/* Prépare le suivi d'une nouvelle phase d'intégration. */
+static loading_params *g_study_project_prepare_content_loading(GStudyProject *);
+
+/*  Efface le suivi d'une phase d'intégration obsolète. */
+static void g_study_project_destroy_content_loading(GStudyProject *, loading_params *);
+
+/* Retrouve les infos de chargements liées à une exploration. */
+static loading_params *g_study_project_find_exploration(GStudyProject *, gid_t, const gid_t **);
+
+/* Assure l'intégration de contenus listés dans du XML. */
+static void g_study_project_recover_binary_contents(GStudyProject *, xmlDoc *, xmlXPathContext *);
+
+/* Note la fin d'une phase d'exploration de contenu. */
+static void on_new_content_explored(GContentExplorer *, gid_t, GStudyProject *);
+
+/* Note la fin d'une phase de resolution de contenu. */
+static void on_new_content_resolved(GContentResolver *, gid_t, GStudyProject *);
+
+/* Réceptionne la recette d'une analyse de contenu. */
+static void on_loaded_content_analyzed(GLoadedContent *, gboolean, GStudyProject *);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -126,6 +154,13 @@ G_DEFINE_TYPE(GStudyProject, g_study_project, G_TYPE_OBJECT);
 
 static void g_study_project_class_init(GStudyProjectClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_study_project_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_study_project_finalize;
+
     g_signal_new("content-added",
                  G_TYPE_STUDY_PROJECT,
                  G_SIGNAL_RUN_LAST,
@@ -159,8 +194,104 @@ static void g_study_project_class_init(GStudyProjectClass *klass)
 
 static void g_study_project_init(GStudyProject *project)
 {
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+
+    project->filename = NULL;
+
+    project->ld_params = NULL;
+    project->ld_count = 0;
+    g_mutex_init(&project->ld_mutex);
+
+    project->contents = NULL;
+    project->count = 0;
     g_mutex_init(&project->mutex);
 
+    explorer = get_current_content_explorer();
+    g_signal_connect(explorer, "explored", G_CALLBACK(on_new_content_explored), project);
+    g_object_unref(G_OBJECT(explorer));
+
+    resolver = get_current_content_resolver();
+    g_signal_connect(resolver, "resolved", G_CALLBACK(on_new_content_resolved), project);
+    g_object_unref(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_study_project_dispose(GStudyProject *project)
+{
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+    size_t i;                               /* Boucle de parcours          */
+
+    explorer = get_current_content_explorer();
+    g_signal_handlers_disconnect_by_func(explorer, G_CALLBACK(on_new_content_explored), project);
+    g_object_unref(G_OBJECT(explorer));
+
+    resolver = get_current_content_resolver();
+    g_signal_handlers_disconnect_by_func(resolver, G_CALLBACK(on_new_content_resolved), project);
+    g_object_unref(G_OBJECT(resolver));
+
+    g_mutex_lock(&project->ld_mutex);
+
+    while (project->ld_count > 0)
+        g_study_project_destroy_content_loading(project, project->ld_params);
+
+    if (project->ld_params != NULL)
+        free(project->ld_params);
+
+    g_mutex_unlock(&project->ld_mutex);
+
+    g_mutex_clear(&project->ld_mutex);
+
+    g_mutex_lock(&project->mutex);
+
+    for (i = 0; i < project->count; i++)
+        g_object_unref(G_OBJECT(project->contents[i]));
+
+    if (project->contents != NULL)
+        free(project->contents);
+
+    g_mutex_unlock(&project->mutex);
+
+    g_mutex_clear(&project->mutex);
+
+    G_OBJECT_CLASS(g_study_project_parent_class)->dispose(G_OBJECT(project));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_study_project_finalize(GStudyProject *project)
+{
+    if (project->filename != NULL)
+        free(project->filename);
+
+    G_OBJECT_CLASS(g_study_project_parent_class)->finalize(G_OBJECT(project));
+
 }
 
 
@@ -201,25 +332,9 @@ GStudyProject *g_study_project_new(void)
 
 GStudyProject *g_study_project_open(const char *filename)
 {
-    return NULL;
-
-#if 0
-
     GStudyProject *result;                  /* Adresse à retourner         */
-    xmlDocPtr xdoc;                         /* Structure XML chargée       */
-    xmlXPathContextPtr context;             /* Contexte pour les XPath     */
-    unsigned int root_contents;             /* Quantité de contenus majeurs*/
-    GAsyncQueue *sema;                      /* Sémaphore taisant son nom   */
-    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
-    unsigned int i;                         /* Boucle de parcours          */
-    size_t access_len;                      /* Taille d'un chemin interne  */
-    char *access;                           /* Chemin pour une sous-config.*/
-    GBinContent *content;                   /* Contenu binaire retrouvé    */
-    long state;                             /* Etat de ce contenu binaire  */
-    bool status;                            /* Bilan d'une lecture         */
-    GDelayedStudy *dstudy;                  /* Etude complémentaire à mener*/
-    GBinaryLoader *loader;                  /* Dispositif de chargement    */
-    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    xmlDoc *xdoc;                           /* Structure XML chargée       */
+    xmlXPathContext *context;               /* Contexte pour les XPath     */
 
     if (!open_xml_file(filename, &xdoc, &context)) return NULL;
 
@@ -227,186 +342,416 @@ GStudyProject *g_study_project_open(const char *filename)
 
     result->filename = strdup(filename);
 
-    /* Préparations aux traitements parallèles */
+    g_study_project_recover_binary_contents(result, xdoc, context);
 
-    root_contents = 0;
+    return result;
 
-    sema = g_async_queue_new();
+}
 
-    void ack_content_processing(GDelayedStudy *dstudy, GAsyncQueue *aqueue)
-    {
-        g_async_queue_push(aqueue, GINT_TO_POINTER(1));
-    }
 
-    /* Chargement des contenus binaires attachés */
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project  = project à sauvegarder.                            *
+*                filename = nom de fichier à utiliser ou NULL pour l'existant.*
+*                                                                             *
+*  Description : Procède à l'enregistrement d'un projet donné.                *
+*                                                                             *
+*  Retour      : true si l'enregistrement s'est déroule sans encombre.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_study_project_save(GStudyProject *project, const char *filename)
+{
+    bool result;                            /* Bilan à retourner           */
+    xmlDocPtr xdoc;                         /* Document XML à créer        */
+    xmlXPathContextPtr context;             /* Contexte pour les recherches*/
+    const char *final;                      /* Lieu d'enregistrement final */
+    size_t root_count;                      /* Quantité d'origines         */
+    size_t i;                               /* Boucle de parcours          */
+    GBinContent *content;                   /* Contenu brut à manipuler    */
+    GBinContent *root;                      /* Contenu d'origine à traiter */
+    const gchar *hash;                      /* Empreinte d'un contenu      */
+    char *access;                           /* Chemin pour une sous-config.*/
+    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
+    const char *format;                     /* Format associé à un élément */
+
+    /* Forme générale */
+
+    result = create_new_xml_file(&xdoc, &context);
+
+    if (result)
+        result = (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL);
+
+    if (result)
+        result = add_string_attribute_to_node(xdoc, context, "/ChrysalideProject", "version", PROJECT_XML_VERSION);
+
+    if (result)
+        result = (ensure_node_exist(xdoc, context, "/ChrysalideProject/RootContents") != NULL);
+
+    if (result)
+        result = (ensure_node_exist(xdoc, context, "/ChrysalideProject/LoadedContents") != NULL);
+
+    final = filename != NULL ? filename : project->filename;
+
+    /* Inscriptions des contenus */
+
+    root_count = 0;
 
-    xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content");
+    g_mutex_lock(&project->mutex);
 
-    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
+    for (i = 0; i < project->count && result; i++)
     {
-        access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+        content = g_loaded_content_get_content(project->contents[i]);
 
-        access = calloc(access_len, sizeof(char));
-        snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1);
+        /* Racine */
 
-        content = g_binary_content_new_from_xml(context, access, filename);
-        status = get_node_prop_long_value(context, access, "state", &state);
+        root = g_binary_content_get_root(content);
 
-        free(access);
+        hash = g_binary_content_get_checksum(root);
 
-        if (content == NULL)
-        {
-            log_variadic_message(LMT_ERROR, _("Unable to load the binary content #%u ; skipping..."), i);
-            continue;
-        }
+        asprintf(&access, "/ChrysalideProject/RootContents/Content[@hash='%s']", hash);
 
-        if (!status)
-        {
-            log_variadic_message(LMT_ERROR, _("Bad state for content '%s' ; skipping..."),
-                                 g_binary_content_describe(content, true));
-            continue;
-        }
+        xobject = get_node_xpath_object(context, access);
 
-        /* Le contenu peut être un conteneur ? */
-        if (state == PCS_ROOT)
+        free(access);
+
+        if (XPATH_OBJ_NODES_COUNT(xobject) == 0)
         {
-            dstudy = g_delayed_study_new(result, content, state);
-            g_signal_connect(dstudy, "work-completed", G_CALLBACK(ack_content_processing), sema);
+            asprintf(&access, "/ChrysalideProject/RootContents/Content[position()=%zu]", ++root_count);
+
+            if (result)
+                result = (ensure_node_exist(xdoc, context, access) != NULL);
 
-            g_delayed_study_preload_only(dstudy);
+            if (result)
+            {
+                hash = g_binary_content_get_checksum(content);
+                result = add_string_attribute_to_node(xdoc, context, access, "hash", hash);
+            }
 
-            root_contents++;
+            if (result)
+                result = g_binary_content_save(root, xdoc, context, access, final);
 
-            study_new_content(dstudy);
+            free(access);
 
         }
 
-    }
+        if(xobject != NULL)
+            xmlXPathFreeObject(xobject);
 
-    if(xobject != NULL)
-        xmlXPathFreeObject(xobject);
+        /* Charge utile */
 
-    /* Attente pour la réception de contenus supplémentaires éventuels */
+        asprintf(&access, "/ChrysalideProject/LoadedContents/Content[position()=%zu]", i + 1);
 
-    for (i = 0; i < root_contents; i++)
-        g_async_queue_pop(sema);
+        if (result)
+            result = (ensure_node_exist(xdoc, context, access) != NULL);
 
-    g_async_queue_unref(sema);
+        if (result)
+        {
+            hash = g_binary_content_get_checksum(content);
+            result = add_string_attribute_to_node(xdoc, context, access, "hash", hash);
+        }
 
-    /* Chargement des binaires analysés */
+        if (result)
+        {
+            format = g_loaded_content_get_format_name(project->contents[i]);
+            result = add_string_attribute_to_node(xdoc, context, access, "format", format);
+        }
 
-    xobject = get_node_xpath_object(context, "/ChrysalideProject/Binaries/Binary");
+        if (result)
+            result = g_loaded_content_save(project->contents[i], xdoc, context, access);
 
-    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
-    {
-        access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+        free(access);
 
-        access = calloc(access_len, sizeof(char));
-        snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%u]", i + 1);
+        g_object_unref(G_OBJECT(content));
 
-        loader = g_binary_loader_new_from_xml(filename, access, result);
+    }
 
-        free(access);
+    g_mutex_unlock(&project->mutex);
 
-        queue = get_work_queue();
-        g_work_queue_schedule_work(queue, G_DELAYED_WORK(loader), DEFAULT_WORK_GROUP);
+    /* Sauvegarde finale */
 
-    }
+    if (result)
+        result = save_xml_file(xdoc, final);
 
-    if(xobject != NULL)
-        xmlXPathFreeObject(xobject);
+    if (result && filename != NULL)
+    {
+        if (project->filename != NULL) free(project->filename);
+        project->filename = strdup(filename);
 
-    /* Fin du chargement */
+    }
 
     close_xml_file(xdoc, context);
 
     return result;
 
-#endif
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = project à consulter.                               *
+*                                                                             *
+*  Description : Indique le chemin du fichier destiné à la sauvegarde.        *
+*                                                                             *
+*  Retour      : Chemin de fichier pour l'enregistrement ou NULL si indéfini. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_study_project_get_filename(const GStudyProject *project)
+{
+    return project->filename;
 
 }
 
 
+
+/* ---------------------------------------------------------------------------------- */
+/*                          INTEGRATION DE CONTENUS BINAIRES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project  = project à sauvegarder.                            *
-*                filename = nom de fichier à utiliser ou NULL pour l'existant.*
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
 *                                                                             *
-*  Description : Procède à l'enregistrement d'un projet donné.                *
+*  Description : Prépare le suivi d'une nouvelle phase d'intégration.         *
 *                                                                             *
-*  Retour      : true si l'enregistrement s'est déroule sans encombre.        *
+*  Retour      : Nouvelle structure de suivi prête à être complétée.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_study_project_save(GStudyProject *project, const char *filename)
+static loading_params *g_study_project_prepare_content_loading(GStudyProject *project)
 {
-    return false;
+    loading_params *result;             /* Trouvaille à retourner      */
 
-#if 0
+    assert(!g_mutex_trylock(&project->ld_mutex));
 
-    bool result;                            /* Bilan à retourner           */
-    xmlDocPtr xdoc;                         /* Document XML à créer        */
-    xmlXPathContextPtr context;             /* Contexte pour les recherches*/
-    const char *final;                      /* Lieu d'enregistrement final */
-    size_t i;                               /* Boucle de parcours          */
-    char *access;                           /* Chemin pour une sous-config.*/
+    project->ld_params = (loading_params *)realloc(project->ld_params,
+                                                   ++project->ld_count * sizeof(loading_params));
 
-    result = create_new_xml_file(&xdoc, &context);
+    result = &project->ld_params[project->ld_count - 1];
 
-    if (result)
-        result = (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL);
+    return result;
 
-    final = filename != NULL ? filename : project->filename;
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
+*                params  = paramètres de chargemeent à supprimer.             *
+*                                                                             *
+*  Description : Efface le suivi d'une phase d'intégration obsolète.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_study_project_destroy_content_loading(GStudyProject *project, loading_params *params)
+{
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+    size_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Indice des paramètres       */
+
+    assert(!g_mutex_trylock(&project->ld_mutex));
 
-    /* Enregistrement des binaires analysés */
+    /* Supression des groupes de travail */
 
-    for (i = 0; i < project->binaries_count && result; i++)
+    explorer = get_current_content_explorer();
+    resolver = get_current_content_resolver();
+
+    if (params->exp_count == 1)
     {
-        asprintf(&access, "/ChrysalideProject/Binaries/Binary[position()=%zu]", i + 1);
+        g_content_resolver_delete_group(resolver, *params->exp_gid);
+        g_content_explorer_delete_group(explorer, *params->exp_gid);
+    }
 
-        result = g_loaded_binary_save(project->binaries[i]->binary, xdoc, context, access, final);
+    else
+    {
+        for (i = 0; i < params->exp_count; i++)
+        {
+            g_content_resolver_delete_group(resolver, *params->exp_gids[i]);
+            g_content_explorer_delete_group(explorer, *params->exp_gids[i]);
+        }
 
-        free(access);
+        free(params->exp_gids);
 
     }
 
-    /* Sauvegarde finale */
+    g_object_unref(G_OBJECT(explorer));
+    g_object_unref(G_OBJECT(resolver));
 
-    result &= save_xml_file(xdoc, final);
+    /* Fermture de l'éventuel fichier XML de chargement */
 
-    if (result && filename != NULL)
+    if (params->xdoc != NULL)
+        close_xml_file(params->xdoc, params->context);
+
+    /* Réorganisation de la liste */
+
+    index = params - project->ld_params;
+
+    if ((index + 1) < project->ld_count)
+        memmove(&project->ld_params[index], &project->ld_params[index + 1],
+                (project->ld_count - index - 1) * sizeof(loading_params));
+
+    project->ld_params = (loading_params *)realloc(project->ld_params,
+                                                   --project->ld_count * sizeof(loading_params));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à consulter.            *
+*                gid     = identifiant du groupe d'exploration recherché.     *
+*                ptr     = pointeur vers la valeur d'origine externe.         *
+*                                                                             *
+*  Description : Retrouve les infos de chargements liées à une exploration.   *
+*                                                                             *
+*  Retour      : Informations trouvées ou NULL en cas d'échec.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static loading_params *g_study_project_find_exploration(GStudyProject *project, gid_t gid, const gid_t **ptr)
+{
+    loading_params *result;             /* Trouvaille à retourner      */
+    const gid_t *value;                 /* Raccourci de confort        */
+    size_t i;                           /* Boucle de parcours #1       */
+    size_t k;                           /* Boucle de parcours #2       */
+
+    assert(!g_mutex_trylock(&project->ld_mutex));
+
+    result = NULL;
+
+    value = NULL;
+
+    for (i = 0; i < project->ld_count && result == NULL; i++)
     {
-        if (project->filename != NULL) free(project->filename);
-        project->filename = strdup(filename);
+        if (project->ld_params[i].exp_count == 1)
+        {
+            value = project->ld_params[i].exp_gid;
+
+            if (*value == gid)
+                result = &project->ld_params[i];
+
+        }
+
+        else
+            for (k = 0; k < project->ld_params[i].exp_count && result == NULL; k++)
+            {
+                value = project->ld_params[i].exp_gids[k];
+
+                if (*value == gid)
+                    result = &project->ld_params[i];
+
+            }
 
     }
 
-    close_xml_file(xdoc, context);
+    if (ptr != NULL)
+    {
+        assert(result == NULL || value != NULL);
+        *ptr = (result == NULL ? NULL : value);
+    }
 
     return result;
 
-#endif
-
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = project à consulter.                               *
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
 *                                                                             *
-*  Description : Indique le chemin du fichier destiné à la sauvegarde.        *
+*  Description : Assure l'intégration de contenus listés dans du XML.         *
 *                                                                             *
-*  Retour      : Chemin de fichier pour l'enregistrement ou NULL si indéfini. *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_study_project_get_filename(const GStudyProject *project)
+static void g_study_project_recover_binary_contents(GStudyProject *project, xmlDoc *xdoc, xmlXPathContext *context)
 {
-    return project->filename;
+    loading_params *params;                 /* Informations de chargement  */
+    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
+    size_t count;                           /* Nombre de contenus premiers */
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
+    size_t explored;                        /* Qté. d'explorations lancées */
+    size_t i;                               /* Boucle de parcours          */
+    char *access;                           /* Chemin pour un contenu      */
+    GBinContent *content;                   /* Contenu binaire retrouvé    */
+
+    xobject = get_node_xpath_object(context, "/ChrysalideProject/RootContents/Content");
+
+    count = XPATH_OBJ_NODES_COUNT(xobject);
+
+    if (count > 0)
+    {
+        explorer = get_current_content_explorer();
+
+        g_mutex_lock(&project->ld_mutex);
+
+        params = g_study_project_prepare_content_loading(project);
+
+        if (count > 1)
+            params->exp_gids = (const gid_t **)malloc(count * sizeof(gid_t *));
+
+        params->resolved = 0;
+
+        params->xdoc = xdoc;
+        params->context = context;
+
+        explored = 0;
+
+        for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
+        {
+            asprintf(&access, "/ChrysalideProject/RootContents/Content[position()=%zu]", i + 1);
+
+            content = g_binary_content_new_from_xml(context, access, project->filename);
+
+            free(access);
+
+            if (content == NULL)
+            {
+                log_variadic_message(LMT_ERROR, _("Unable to load the root content #%zu ; skipping..."), i);
+                continue;
+            }
+
+            if (count == 1)
+            {
+                params->exp_gid = g_content_explorer_create_group(explorer, content);
+                explored++;
+            }
+            else
+                params->exp_gids[explored++] = g_content_explorer_create_group(explorer, content);
+
+            g_object_unref(G_OBJECT(content));
+
+        }
+
+        params->exp_count = explored;
+
+        g_mutex_unlock(&project->ld_mutex);
+
+        g_object_unref(G_OBJECT(explorer));
+
+    }
+
+    if(xobject != NULL)
+        xmlXPathFreeObject(xobject);
 
 }
 
@@ -415,9 +760,8 @@ const char *g_study_project_get_filename(const GStudyProject *project)
 *                                                                             *
 *  Paramètres  : project = projet dont le contenu est à compléter.            *
 *                content = contenu binaire à mémoriser pour le projet.        *
-*                state   = état du contenu à conserver.                       *
 *                                                                             *
-*  Description : Assure l'intégration d'un contenu binaire dans un projet.    *
+*  Description : Assure l'intégration de contenus binaires dans un projet.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -425,77 +769,246 @@ const char *g_study_project_get_filename(const GStudyProject *project)
 *                                                                             *
 ******************************************************************************/
 
-void g_study_project_add_binary_content(GStudyProject *project, GBinContent *content, ProjectContentState state)
+void g_study_project_discover_binary_content(GStudyProject *project, GBinContent *content)
 {
-#if 0
+    loading_params *params;                 /* Informations de chargement  */
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
 
-    loaded_content *new;                    /* Nouveau contenu à définir   */
+    explorer = get_current_content_explorer();
 
-    g_mutex_lock(&project->cnt_mutex);
+    g_mutex_lock(&project->ld_mutex);
 
-    project->contents = (loaded_content *)realloc(project->contents,
-                                                  ++project->contents_count * sizeof(loaded_content));
+    params = g_study_project_prepare_content_loading(project);
 
-    new = &project->contents[project->contents_count - 1];
+    params->exp_gid = g_content_explorer_create_group(explorer, content);
+    params->exp_count = 1;
 
-    g_object_ref(G_OBJECT(content));
+    params->resolved = 0;
 
-    new->content = content;
-    new->state = state;
+    params->xdoc = NULL;
+    params->context = NULL;
 
-    g_mutex_unlock(&project->cnt_mutex);
+    g_mutex_unlock(&project->ld_mutex);
 
-#endif
+    g_object_unref(G_OBJECT(explorer));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = projet dont le contenu est à compléter.            *
-*                hash    = empreinte du contenu à retrouver.                  *
+*  Paramètres  : explorer = gestionnaire d'explorations à consulter.          *
+*                gid      = groupe d'exploration concerné.                    *
+*                project  = projet avide des résultats des opérations.        *
 *                                                                             *
-*  Description : Recherche un contenu binaire du projet selon son empreinte.  *
+*  Description : Note la fin d'une phase d'exploration de contenu.            *
 *                                                                             *
-*  Retour      : Contenu avec propriété transférée ou NULL en cas d'échec.    *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, const char *hash)
+static void on_new_content_explored(GContentExplorer *explorer, gid_t gid, GStudyProject *project)
 {
-    return NULL;
+    const gid_t *gid_ptr;                   /* Référence vers l'origine    */
+    loading_params *params;                 /* Informations de chargement  */
+    GBinContent **available;                /* Contenus binaires présents  */
+    size_t count;                           /* Quantité de ces contenus    */
+    const wgroup_id_t *wid;                 /* Groupe de tâches            */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+    size_t i;                               /* Boucle de parcours          */
 
-#if 0
+    g_mutex_lock(&project->ld_mutex);
+
+    params = g_study_project_find_exploration(project, gid, &gid_ptr);
+
+    /* S'il s'agit bien d'une exploration nouvelle */
+    if (params != NULL)
+    {
+        wid = g_content_explorer_get_group_work_id(explorer, gid);
+
+        available = g_content_explorer_get_all(explorer, gid, &count);
+        assert(count > 0);
+
+        resolver = get_current_content_resolver();
+
+        g_content_resolver_create_group(resolver, wid, gid_ptr, available, count);
+
+        g_object_unref(G_OBJECT(resolver));
+
+        for (i = 0; i < count; i++)
+           g_object_unref(G_OBJECT(available[i]));
 
-    GBinContent *result;                    /* Trouvaille à retourner      */
+        free(available);
+
+    }
+
+    g_mutex_unlock(&project->ld_mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = gestionnaire de résolutions à consulter.          *
+*                gid      = groupe d'exploration concerné.                    *
+*                project  = projet avide des résultats des opérations.        *
+*                                                                             *
+*  Description : Note la fin d'une phase de resolution de contenu.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_new_content_resolved(GContentResolver *resolver, gid_t gid, GStudyProject *project)
+{
+    loading_params *params;                 /* Informations de chargement  */
+    GLoadedContent **available;             /* Contenus chargés valables   */
+    size_t count;                           /* Quantité de ces contenus    */
     size_t i;                               /* Boucle de parcours          */
-    GBinContent *iter;                      /* Contenu binaire analysé     */
-    const gchar *other;                     /* Autre empreinte à comparer  */
+    GBinContent *content;                   /* Contenu brut à manipuler    */
+    const gchar *hash;                      /* Empreinte d'un contenu      */
+    const char *format;                     /* Format associé à un élément */
+    char *access;                           /* Chemin pour une sous-config.*/
+    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
+    bool status;                            /* Bilan d'une restauration    */
 
-    result = NULL;
+    g_mutex_lock(&project->ld_mutex);
 
-    g_mutex_lock(&project->cnt_mutex);
+    params = g_study_project_find_exploration(project, gid, NULL);
 
-    for (i = 0; i < project->contents_count && result == NULL; i++)
+    /* S'il s'agit bien d'une exploration nouvelle */
+    if (params != NULL)
     {
-        iter = project->contents[i].content;
-        other = g_binary_content_get_checksum(iter);
+        available = g_content_resolver_get_all(resolver, gid, &count);
 
-        if (strcmp(hash, other) == 0)
+        /* Rechargement à partir d'XML ? */
+        if (params->xdoc != NULL)
         {
-            g_object_ref(G_OBJECT(iter));
-            result = iter;
+            assert(params->context != NULL);
+
+            for (i = 0; i < count; i++)
+            {
+                content = g_loaded_content_get_content(available[i]);
+                hash = g_binary_content_get_checksum(content);
+                g_object_unref(G_OBJECT(content));
+
+                format = g_loaded_content_get_format_name(available[i]);
+
+                asprintf(&access, "/ChrysalideProject/LoadedContents/Content[@hash='%s' and @format='%s']",
+                         hash, format);
+
+                xobject = get_node_xpath_object(params->context, access);
+
+                if (XPATH_OBJ_NODES_COUNT(xobject) > 0)
+                {
+
+                    status = g_loaded_content_restore(available[i], params->xdoc, params->context, access);
+
+                    if (!status)
+                        log_variadic_message(LMT_ERROR,
+                                             _("Unable to reload binary from XML (hash=%s) ; skipping..."), hash);
+
+                    else
+                    {
+                        /**
+                         * S'il s'agit des résultats de la dernière exploration,
+                         * alors les groupes contenant les éléments chargés vont
+                         * être libéré, potentiellement pendant l'analyse.
+                         *
+                         * On temporise en incrémentant les références.
+                         */
+                        g_object_ref(G_OBJECT(available[i]));
+
+                        g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project);
+
+                        g_loaded_content_analyze(available[i]);
+
+                    }
+
+                }
+
+                free(access);
+
+                if(xobject != NULL)
+                    xmlXPathFreeObject(xobject);
+
+                g_object_unref(G_OBJECT(available[i]));
+
+            }
+
+        }
+
+        /* Découverte(s) initiale(s) ? */
+        else
+        {
+            for (i = 0; i < count; i++)
+            {
+                /**
+                 * S'il s'agit des résultats de la dernière exploration,
+                 * alors les groupes contenant les éléments chargés vont
+                 * être libéré, potentiellement pendant l'analyse.
+                 *
+                 * On temporise en incrémentant les références.
+                 */
+                g_object_ref(G_OBJECT(available[i]));
+
+                g_signal_connect(available[i], "analyzed", G_CALLBACK(on_loaded_content_analyzed), project);
+
+                g_loaded_content_analyze(available[i]);
+
+                g_object_unref(G_OBJECT(available[i]));
+
+            }
+
         }
 
+        /* Dans tous les cas... */
+        if (available != NULL)
+            free(available);
+
+        /* Si c'était la dernière résolution... */
+        if (++params->resolved == params->exp_count)
+            g_study_project_destroy_content_loading(project, params);
+
     }
 
-    g_mutex_unlock(&project->cnt_mutex);
+    g_mutex_unlock(&project->ld_mutex);
 
-    return result;
+}
 
-#endif
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu chargé et analysé.                         *
+*                success = bilan d'une analyse menée.                         *
+*                project = projet avide des résultats des opérations.         *
+*                                                                             *
+*  Description : Réceptionne la recette d'une analyse de contenu.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStudyProject *project)
+{
+    const char *desc;                       /* Description du contenu      */
+
+    if (success)
+        g_study_project_attach_content(project, content);
+
+    else
+    {
+        desc = g_loaded_content_describe(content, true);
+        log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc);
+    }
+
+    g_object_ref(G_OBJECT(content));
 
 }
 
@@ -521,6 +1034,7 @@ void g_study_project_attach_content(GStudyProject *project, GLoadedContent *cont
                                                    ++project->count * sizeof(GLoadedContent *));
 
     project->contents[project->count - 1] = content;
+    g_object_ref(G_OBJECT(content));
 
     g_mutex_unlock(&project->mutex);
 
@@ -732,7 +1246,7 @@ void push_project_into_recent_list(const GStudyProject *project)
 
     recent.mime_type = "application/chrysalide.project";
     recent.app_name = "Chrysalide";
-    recent.app_exec = "chrysalide %f";
+    recent.app_exec = "chrysalide -p %f";
 
     gtk_recent_manager_add_full(manager, qualified, &recent);
 
diff --git a/src/analysis/project.h b/src/analysis/project.h
index c24ee43..2ee178b 100644
--- a/src/analysis/project.h
+++ b/src/analysis/project.h
@@ -28,20 +28,23 @@
 #include <gtk/gtk.h>
 
 
-#include "binary.h"
 #include "loaded.h"
 
 
 
+#define PROJECT_XML_VERSION "2"
+
+
+
 /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
 
 
-#define G_TYPE_STUDY_PROJECT               g_study_project_get_type()
-#define G_STUDY_PROJECT(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_study_project_get_type(), GStudyProject))
-#define G_IS_STUDY_PROJECT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_study_project_get_type()))
-#define G_STUDY_PROJECT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STUDY_PROJECT, GStudyProjectClass))
-#define G_IS_STUDY_PROJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STUDY_PROJECT))
-#define G_STUDY_PROJECT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STUDY_PROJECT, GStudyProjectClass))
+#define G_TYPE_STUDY_PROJECT            g_study_project_get_type()
+#define G_STUDY_PROJECT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STUDY_PROJECT, GStudyProject))
+#define G_IS_STUDY_PROJECT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STUDY_PROJECT))
+#define G_STUDY_PROJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STUDY_PROJECT, GStudyProjectClass))
+#define G_IS_STUDY_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STUDY_PROJECT))
+#define G_STUDY_PROJECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STUDY_PROJECT, GStudyProjectClass))
 
 
 /* Projet d'étude regroupant les binaires analysés (instance) */
@@ -66,22 +69,13 @@ bool g_study_project_save(GStudyProject *, const char *);
 /* Indique le chemin du fichier destiné à la sauvegarde. */
 const char *g_study_project_get_filename(const GStudyProject *);
 
-/* Etat d'un contenu binaire du projet */
-typedef enum _ProjectContentState
-{
-    PCS_ROOT,                               /* Contenu principal           */
-    PCS_INTERNAL,                           /* Contenu dérivé              */
-    PCS_ATTACHED,                           /* Contenu complémentaire      */
 
-    PCS_COUNT
 
-} ProjectContentState;
+/* ------------------------ INTEGRATION DE CONTENUS BINAIRES ------------------------ */
 
-/* Assure l'intégration d'un contenu binaire dans un projet. */
-void g_study_project_add_binary_content(GStudyProject *, GBinContent *, ProjectContentState);
 
-/* Recherche un contenu binaire du projet selon son empreinte. */
-GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *, const char *);
+/* Assure l'intégration de contenus binaires dans un projet. */
+void g_study_project_discover_binary_content(GStudyProject *, GBinContent *);
 
 /* Attache un contenu donné à un projet donné. */
 void g_study_project_attach_content(GStudyProject *, GLoadedContent *);
@@ -111,5 +105,4 @@ void push_project_into_recent_list(const GStudyProject *);
 
 
 
-
 #endif  /* _PROJECT_H */
diff --git a/src/core/core.c b/src/core/core.c
index 2d790ce..1b6b033 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -64,6 +64,8 @@ bool load_all_basic_components(void)
     static bool result = false;             /* Bilan à retourner           */
     char *cfgdir;                           /* Répertoire de configuration */
     GWorkQueue *queue;                      /* Singleton pour tâches       */
+    GContentExplorer *explorer;             /* Explorateur de contenus     */
+    GContentResolver *resolver;             /* Résolveur de contenus       */
 
     /**
      * On mémorise les passages réussis.
@@ -97,6 +99,12 @@ bool load_all_basic_components(void)
         queue = g_work_queue_new();
         set_work_queue(queue);
 
+        explorer = g_content_explorer_new();
+        set_current_content_explorer(explorer);
+
+        resolver = g_content_resolver_new();
+        set_current_content_resolver(resolver);
+
         result &= init_segment_content_hash_table();
 
         result &= load_hard_coded_processors_definitions();
diff --git a/src/core/global.c b/src/core/global.c
index b227a5d..decf300 100644
--- a/src/core/global.c
+++ b/src/core/global.c
@@ -31,6 +31,12 @@
 /* Gestionnaire de tâches parallèles */
 static GWorkQueue *_queue = NULL;
 
+/* Explorateur de contenus */
+static GContentExplorer *_explorer = NULL;
+
+/* Résolveur de contenus */
+static GContentResolver *_resolver = NULL;
+
 /* Projet global actif */
 static GStudyProject *_project = NULL;
 
@@ -81,6 +87,96 @@ GWorkQueue *get_work_queue(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : explorer = éventuelle adresse du nouveau gestionnaire.       *
+*                                                                             *
+*  Description : Définit l'adresse de l'explorateur de contenus courant.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_current_content_explorer(GContentExplorer *explorer)
+{
+    if (_explorer != NULL)
+        g_object_unref(G_OBJECT(_explorer));
+
+    _explorer = explorer;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit l'adresse de l'explorateur de contenus courant.      *
+*                                                                             *
+*  Retour      : Adresse de l'explorateur global ou NULL si aucun (!).        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GContentExplorer *get_current_content_explorer(void)
+{
+    assert(_explorer != NULL);
+
+    g_object_ref(G_OBJECT(_explorer));
+
+    return _explorer;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = éventuelle adresse du nouveau gestionnaire.       *
+*                                                                             *
+*  Description : Définit l'adresse du résolveur de contenus courant.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_current_content_resolver(GContentResolver *resolver)
+{
+    if (_resolver != NULL)
+        g_object_unref(G_OBJECT(_resolver));
+
+    _resolver = resolver;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit l'adresse du résolveur de contenus courant.          *
+*                                                                             *
+*  Retour      : Adresse du résolveur global ou NULL si aucun (!).            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GContentResolver *get_current_content_resolver(void)
+{
+    assert(_resolver != NULL);
+
+    g_object_ref(G_OBJECT(_resolver));
+
+    return _resolver;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : project = éventuelle adresse du nouveau projet principal.    *
 *                                                                             *
 *  Description : Définit l'adresse du projet courant.                         *
@@ -112,7 +208,7 @@ void set_current_project(GStudyProject *project)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = éventuel adresse à renvoyer désormais.             *
+*  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit l'adresse du projet courant.                         *
 *                                                                             *
diff --git a/src/core/global.h b/src/core/global.h
index 6cf029f..5f01909 100644
--- a/src/core/global.h
+++ b/src/core/global.h
@@ -25,6 +25,7 @@
 #define _CORE_GLOBAL_H
 
 
+#include "../analysis/loading.h"
 #include "../analysis/project.h"
 #include "../glibext/delayed.h"
 
@@ -36,6 +37,18 @@ void set_work_queue(GWorkQueue *);
 /* Fournit le gestionnaire de traitements parallèles courant. */
 GWorkQueue *get_work_queue(void);
 
+/* Définit l'adresse de l'explorateur de contenus courant. */
+void set_current_content_explorer(GContentExplorer *);
+
+/* Fournit l'adresse de l'explorateur de contenus courant. */
+GContentExplorer *get_current_content_explorer(void);
+
+/* Définit l'adresse du résolveur de contenus courant. */
+void set_current_content_resolver(GContentResolver *);
+
+/* Fournit l'adresse du résolveur de contenus courant. */
+GContentResolver *get_current_content_resolver(void);
+
 /* Définit l'adresse du projet courant. */
 void set_current_project(GStudyProject *);
 
diff --git a/src/format/format-int.h b/src/format/format-int.h
index 78da2f6..37dac0f 100644
--- a/src/format/format-int.h
+++ b/src/format/format-int.h
@@ -37,6 +37,12 @@
 /* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */
 
 
+/* Indique la désignation interne du format. */
+typedef const char * (* format_get_name_fc) (const GBinFormat *);
+
+/*Assure l'interprétation d'un format en différé. */
+typedef bool (* format_analyze_fc) (GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Indique le boutisme employé par le format binaire analysé. */
 typedef SourceEndian (* format_get_endian_fc) (const GBinFormat *);
 
@@ -109,6 +115,10 @@ struct _GBinFormatClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+    format_get_name_fc get_name;            /* Désignation interne         */
+
+    format_analyze_fc analyze;              /* Interprétation du format    */
+
     format_get_endian_fc get_endian;        /* Boutisme employé            */
 
     format_complete_analysis_fc complete;   /* Terminaison d'analyse       */
diff --git a/src/format/format.c b/src/format/format.c
index 29709c9..675fd2f 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -262,6 +262,54 @@ GBinContent *g_binary_format_get_content(const GBinFormat *format)
 *                                                                             *
 *  Paramètres  : format = description de l'exécutable à consulter.            *
 *                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_binary_format_get_name(const GBinFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = G_BIN_FORMAT_GET_CLASS(format)->get_name(format);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure l'interprétation d'un format en différé.              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_analyze(GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = G_BIN_FORMAT_GET_CLASS(format)->analyze(format, gid, status);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
 *  Description : Indique le boutisme employé par le format binaire analysé.   *
 *                                                                             *
 *  Retour      : Boutisme associé au format.                                  *
diff --git a/src/format/format.h b/src/format/format.h
index 806c14f..982907c 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -33,7 +33,7 @@
 #include "symbol.h"
 #include "../analysis/content.h"
 #include "../arch/context.h"
-#include "../gtkext/gtkstatusstack.h"
+#include "../glibext/delayed.h"
 
 
 
@@ -58,6 +58,12 @@ GType g_binary_format_get_type(void);
 /* Fournit une référence vers le contenu binaire analysé. */
 GBinContent *g_binary_format_get_content(const GBinFormat *);
 
+/* Indique la désignation interne du format. */
+const char *g_binary_format_get_name(const GBinFormat *);
+
+/* Assure l'interprétation d'un format en différé. */
+bool g_binary_format_analyze(GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Indique le boutisme employé par le format binaire analysé. */
 SourceEndian g_binary_format_get_endianness(const GBinFormat *);
 
diff --git a/src/glibext/delayed-int.h b/src/glibext/delayed-int.h
index 2e1b4be..6ffff75 100644
--- a/src/glibext/delayed-int.h
+++ b/src/glibext/delayed-int.h
@@ -21,6 +21,10 @@
  */
 
 
+#ifndef _GLIBEXT_DELAYED_INT_H
+#define _GLIBEXT_DELAYED_INT_H
+
+
 #include "delayed.h"
 
 
@@ -65,3 +69,7 @@ struct _GDelayedWorkClass
 
 #define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
 #define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
+
+
+
+#endif  /* _GLIBEXT_DELAYED_INT_H */
diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c
index b7793cd..78c8a10 100644
--- a/src/glibext/delayed.c
+++ b/src/glibext/delayed.c
@@ -123,6 +123,9 @@ static void g_work_group_schedule(GWorkGroup *, GDelayedWork *);
 /* Assure le traitement en différé. */
 static void *g_work_group_process(GWorkGroup *);
 
+/* Détermine si le groupe est vide de toute programmation. */
+static bool g_work_group_is_empty(GWorkGroup *);
+
 /* Attend que toutes les tâches d'un groupe soient traitées. */
 static void g_work_group_wait_for_completion(GWorkGroup *, GWorkQueue *);
 
@@ -607,6 +610,46 @@ static void *g_work_group_process(GWorkGroup *group)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : group = gestionnaire des actions à consulter.                *
+*                                                                             *
+*  Description : Détermine si le groupe est vide de toute programmation.      *
+*                                                                             *
+*  Retour      : Etat du groupe de travail.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_work_group_is_empty(GWorkGroup *group)
+{
+    bool result;                            /* Etat à retourner            */
+
+    /**
+     * Pour que le résultat soit exploitable, il ne doit pas varier
+     * en dehors de la zone couverte par le verrou du groupe avant
+     * son utilisation par l'appelant.
+     *
+     * Il doit donc logiquement y avoir un autre verrou en amont et,
+     * comme à priori on ne devrait pas bloquer le groupe principal
+     * pour un traitement particulier, on ajoute ici une simple vérification
+     * de bonne pratique.
+     */
+
+    assert(group->id != DEFAULT_WORK_GROUP);
+
+    g_mutex_lock(&group->mutex);
+
+    result = dl_list_empty(group->works);
+
+    g_mutex_unlock(&group->mutex);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : group = groupe dont les conclusions sont attendues.          *
 *                queue = queue d'appartenance pour les appels externes.       *
 *                                                                             *
@@ -911,6 +954,13 @@ wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
 void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
 {
     size_t i;                               /* Boucle de parcours          */
+#ifndef NDEBUG
+    bool found;                             /* Repérage du groupe visé     */
+#endif
+
+#ifndef NDEBUG
+    found = false;
+#endif
 
     g_mutex_lock(&queue->mutex);
 
@@ -924,11 +974,15 @@ void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
             queue->groups = (GWorkGroup **)realloc(queue->groups,
                                                    queue->groups_count * sizeof(GWorkGroup *));
 
+#ifndef NDEBUG
+            found = true;
+#endif
+
             break;
 
         }
 
-    assert(i < queue->groups_count);
+    assert(found);
 
     g_mutex_unlock(&queue->mutex);
 
@@ -1010,6 +1064,40 @@ static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *queue, wgroup_id_t
 *  Paramètres  : queue = gestionnaire de l'ensemble des groupes de travail.   *
 *                id    = identifiant d'un groupe de travail.                  *
 *                                                                             *
+*  Description : Détermine si un groupe est vide de toute programmation.      *
+*                                                                             *
+*  Retour      : Etat du groupe de travail.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_work_queue_is_empty(GWorkQueue *queue, wgroup_id_t id)
+{
+    bool result;                            /* Etat à retourner            */
+    GWorkGroup *group;                      /* Groupe de travail à attendre*/
+
+    group = g_work_queue_find_group_for_id(queue, id);
+
+    if (group != NULL)
+    {
+        result = g_work_group_is_empty(group);
+        g_object_unref(G_OBJECT(group));
+    }
+
+    else
+        result = true;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : queue = gestionnaire de l'ensemble des groupes de travail.   *
+*                id    = identifiant d'un groupe de travail.                  *
+*                                                                             *
 *  Description : Attend que toutes les tâches d'un groupe soient traitées.    *
 *                                                                             *
 *  Retour      : -                                                            *
diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h
index 7c620e6..ab43640 100644
--- a/src/glibext/delayed.h
+++ b/src/glibext/delayed.h
@@ -101,6 +101,9 @@ void g_work_queue_delete_work_group(GWorkQueue *, wgroup_id_t);
 /* Place une nouvelle tâche en attente. */
 void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *, wgroup_id_t);
 
+/* Détermine si un groupe est vide de toute programmation. */
+bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
+
 /* Attend que toutes les tâches d'un groupe soient traitées. */
 void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
 
diff --git a/src/gui/editem-int.h b/src/gui/editem-int.h
index a70cc87..801e54c 100644
--- a/src/gui/editem-int.h
+++ b/src/gui/editem-int.h
@@ -32,6 +32,7 @@
 #include <gtk/gtkwidget.h>
 
 
+#include "../analysis/project.h"
 #include "../common/dllist.h"
 #include "../gtkext/gtkdisplaypanel.h"
 
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 7047f32..ea2fe1f 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -1608,7 +1608,7 @@ static void notify_paned_handle_position_change(GObject *obj, GParamSpec *pspec,
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#include "../glibext/signal.h"
 static void notify_editor_project_change(GStudyProject *project, bool new)
 {
 
@@ -1616,7 +1616,9 @@ static void notify_editor_project_change(GStudyProject *project, bool new)
     {
 
 
-        g_signal_connect(project, "content-added", G_CALLBACK(on_editor_loaded_content_added), NULL);
+        g_signal_connect_to_main(project, "content-added", G_CALLBACK(on_editor_loaded_content_added), NULL,
+                               g_cclosure_marshal_VOID__OBJECT);
+
 
 
 
@@ -1630,8 +1632,8 @@ static void notify_editor_project_change(GStudyProject *project, bool new)
 
         g_study_project_hide(project);
 
-
-        g_signal_handlers_disconnect_by_func(project, G_CALLBACK(on_editor_loaded_content_added), NULL);
+        // FIXME
+        //g_signal_handlers_disconnect_by_func(project, G_CALLBACK(on_editor_loaded_content_added), NULL);
 
 
     }
diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c
index 424a506..5a28a7e 100644
--- a/src/gui/menus/project.c
+++ b/src/gui/menus/project.c
@@ -286,8 +286,6 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
         free(dir);
     }
 
-    g_object_unref(G_OBJECT(project));
-
     if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
     {
         filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
@@ -296,7 +294,7 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
 
         if (content != NULL)
         {
-            qck_study_new_content(content, PCS_ROOT);
+            g_study_project_discover_binary_content(project, content);
             g_object_unref(G_OBJECT(content));
         }
 
@@ -304,6 +302,8 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
 
     }
 
+    g_object_unref(G_OBJECT(project));
+
     gtk_widget_destroy(dialog);
 
 }
diff --git a/src/main.c b/src/main.c
index 19b0544..626cae8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -418,18 +418,21 @@ static gboolean load_last_project(GGenConfig *cfg)
 static int open_binaries(char **files, int count)
 {
     int result;                             /* Bilan à retourner           */
+    GStudyProject *project;                 /* Projet courant à compléter  */
     int i;                                  /* Boucle de parcours          */
     GBinContent *content;                   /* Contenu binaire à charger   */
 
     result = EXIT_SUCCESS;
 
+    project = get_current_project();
+
     for (i = 0; i < count && result == EXIT_SUCCESS; i++)
     {
         content = g_file_content_new(files[i]);
 
         if (content != NULL)
         {
-            qck_study_new_content(content, PCS_ROOT);
+            g_study_project_discover_binary_content(project, content);
             g_object_unref(G_OBJECT(content));
         }
 
@@ -438,6 +441,8 @@ static int open_binaries(char **files, int count)
 
     }
 
+    g_object_unref(G_OBJECT(project));
+
     return result;
 
 }
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index d406cc8..4c8194d 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -85,14 +85,20 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
     while (0)
 
 
-/* DPS_FORMAT */
 
-//#define find_matching_format()
 
-#define handle_binary_format(a, f, s)                                     \
+
+/* DPS_CONTENT */
+
+#define handle_binary_content(a, c, i, s) \
+    process_all_plugins_for(a, g_plugin_module_handle_binary_content, c, i, s)
+
+/* DPS_FORMAT */
+
+#define handle_binary_format(a, f, s) \
     process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s)
 
-#define preload_binary_format(a, f, i, s)                                 \
+#define preload_binary_format(a, f, i, s) \
     process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s)
 
 /* DPS_DISASSEMBLY */
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index ed09e91..c32c9e3 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -79,8 +79,9 @@ typedef uint32_t plugin_action_t;
 
 /* DPC_BINARY_PROCESSING */
 
-#define DPS_FORMAT              DEFINE_PLUGIN_SUB_CATEGORY(0)
-#define DPS_DISASSEMBLY         DEFINE_PLUGIN_SUB_CATEGORY(1)
+#define DPS_CONTENT             DEFINE_PLUGIN_SUB_CATEGORY(0)
+#define DPS_FORMAT              DEFINE_PLUGIN_SUB_CATEGORY(1)
+#define DPS_DISASSEMBLY         DEFINE_PLUGIN_SUB_CATEGORY(2)
 
 // GUI -> project
 // binary loaded
@@ -111,6 +112,16 @@ typedef enum _PluginAction
     PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1),
 
     /**
+     * DPC_BINARY_PROCESSING | DPS_CONTENT
+     */
+
+    /* Exploration de contenus binaires */
+    PGA_CONTENT_EXPLORER = DPC_BINARY_PROCESSING | DPS_CONTENT | DEFINE_PLUGIN_ACTION(0),
+
+    /* Conversion de contenus binaires en contenus chargés */
+    PGA_CONTENT_RESOLVER = DPC_BINARY_PROCESSING | DPS_CONTENT | DEFINE_PLUGIN_ACTION(1),
+
+    /**
      * DPC_BINARY_PROCESSING | DPS_FORMAT
      */
 
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 213ae92..5fae2de 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -46,8 +46,8 @@ typedef void (* pg_process_disassembly_fc) (const GPluginModule *, PluginAction,
 
 
 
-/* Indique si le format peut être pris en charge ici. */
-//typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **);
+/* Procède à une opération liée à un contenu binaire. */
+typedef void (* pg_handle_content) (const GPluginModule *, PluginAction, GBinContent *, gid_t, GtkStatusStack *);
 
 /* Procède à une opération liée au format de fichier uniquement. */
 typedef bool (* pg_handle_format) (const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *);
@@ -115,7 +115,7 @@ struct _GPluginModule
     //execute_on_debugger_fc handle_debugger; /* Action liée à un débogueur  */
 
 
-    //pg_format_is_matching is_matching;      /* Recherche de correspondance */
+    pg_handle_content handle_content;       /* Explorations ou résolutions */
     pg_handle_format handle_format;         /* Manipulation du format      */
     pg_preload_format preload_format;       /* Préchargement d'un format   */
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index d9072d7..02684d6 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -260,6 +260,28 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
                 switch (sub)
                 {
+                    case DPS_CONTENT:
+
+                        switch (action)
+                        {
+                            case PGA_CONTENT_EXPLORER:
+                            case PGA_CONTENT_RESOLVER:
+                                if (!load_plugin_symbol(result->module,
+                                                        "chrysalide_plugin_handle_binary_content",
+                                                        &result->handle_content))
+                                    goto bad_plugin;
+                                break;
+
+                            default:
+                                log_variadic_message(LMT_WARNING,
+                                                     _("Unknown action '0x%02x' in plugin '%s'..."),
+                                                     result->interface->actions[i], filename);
+                                break;
+
+                        }
+
+                        break;
+
                     case DPS_FORMAT:
 
                         switch (action)
@@ -684,6 +706,29 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                gid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
+{
+    return plugin->handle_content(plugin, action, content, gid, status);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : plugin = greffon à manipuler.                                *
 *                action = type d'action attendue.                             *
 *                format = format de binaire à manipuler pendant l'opération.  *
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index d86682c..9ac6aa6 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -91,7 +91,8 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *, GPluginModule **, siz
 /* Termine le chargement du greffon préparé. */
 bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t);
 
-
+/* Procède à une opération liée à un contenu binaire. */
+void g_plugin_module_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, gid_t, GtkStatusStack *);
 
 /* Procède à une opération liée au format de fichier uniquement. */
 bool g_plugin_module_handle_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *);
-- 
cgit v0.11.2-87-g4458