From 5d09d85a5e606e5ac458abd37e72b73ce52541cb Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 20 May 2020 00:38:17 +0200
Subject: Improved the use of the known format object.

---
 plugins/bootimg/format.c              |  20 +-
 plugins/pychrysalide/arch/processor.c |  48 ++--
 plugins/pychrysalide/format/known.c   | 427 +++++++++++++++++++++++++++++++---
 plugins/pychrysalide/plugin.c         |   7 +-
 src/format/known-int.h                |   6 +-
 src/format/known.c                    |  20 +-
 src/format/known.h                    |   4 +-
 tests/format/known.py                 |  44 ++++
 8 files changed, 497 insertions(+), 79 deletions(-)
 create mode 100644 tests/format/known.py

diff --git a/plugins/bootimg/format.c b/plugins/bootimg/format.c
index 99b8f27..feeb9f7 100644
--- a/plugins/bootimg/format.c
+++ b/plugins/bootimg/format.c
@@ -48,10 +48,10 @@ static void g_bootimg_format_dispose(GBootImgFormat *);
 static void g_bootimg_format_finalize(GBootImgFormat *);
 
 /* Indique la désignation interne du format. */
-static const char *g_bootimg_format_get_name(const GBootImgFormat *);
+static char *g_bootimg_format_get_key(const GBootImgFormat *);
 
 /* Fournit une description humaine du format. */
-static const char *g_bootimg_format_get_description(const GBootImgFormat *);
+static char *g_bootimg_format_get_description(const GBootImgFormat *);
 
 /* Assure l'interprétation d'un format en différé. */
 static bool g_bootimg_format_analyze(GBootImgFormat *, wgroup_id_t, GtkStatusStack *);
@@ -116,7 +116,7 @@ static void g_bootimg_format_class_init(GBootImgFormatClass *klass)
 
     known = G_KNOWN_FORMAT_CLASS(klass);
 
-    known->get_name = (known_get_name_fc)g_bootimg_format_get_name;
+    known->get_key = (known_get_key_fc)g_bootimg_format_get_key;
     known->get_desc = (known_get_desc_fc)g_bootimg_format_get_description;
     known->analyze = (known_analyze_fc)g_bootimg_format_analyze;
 
@@ -213,17 +213,17 @@ GBootImgFormat *g_bootimg_format_new(GBinContent *content)
 *                                                                             *
 *  Description : Indique la désignation interne du format.                    *
 *                                                                             *
-*  Retour      : Description du format.                                       *
+*  Retour      : Désignation du format.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static const char *g_bootimg_format_get_name(const GBootImgFormat *format)
+static char *g_bootimg_format_get_key(const GBootImgFormat *format)
 {
-    const char *result;                     /* Désignation à retourner     */
+    char *result;                           /* Désignation à retourner     */
 
-    result = "bootimg";
+    result = strdup("bootimg");
 
     return result;
 
@@ -242,11 +242,11 @@ static const char *g_bootimg_format_get_name(const GBootImgFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-static const char *g_bootimg_format_get_description(const GBootImgFormat *format)
+static char *g_bootimg_format_get_description(const GBootImgFormat *format)
 {
-    const char *result;                     /* Désignation à retourner     */
+    char *result;                           /* Description à retourner     */
 
-    result = "Android Boot Image";
+    result = strdup("Android Boot Image");
 
     return result;
 
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 557e7a7..71ef153 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -45,31 +45,6 @@
 
 
 
-#define ARCH_PROCESSOR_DOC                                              \
-    "The ArchProcessor object aims to get subclassed to create"         \
-    " processors for new architectures.\n"                              \
-    "\n"                                                                \
-    "Several items have to be defined as class attributes in the final" \
-    " class:\n"                                                         \
-    "* *_key*: a string providing a small name used to identify the"    \
-    " architecture;\n"                                                  \
-    "* *_desc*: a string for a human readable description of the"       \
-    " new architecture;\n"                                              \
-    "* *_memory_size*: size of the memory space, as a"                  \
-    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
-    "* *_ins_min_size*: size of the smallest instruction, as a"         \
-    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
-    "* *_virtual_space*: a boolean value indicating if the architecture"\
-    " supports a virtual space.\n"                                      \
-    "\n"                                                                \
-    "Calls to the *__init__* constructor of this abstract object expect"\
-    " the following arguments as keyword parameters:\n"                 \
-    "* *endianness*: endianness to apply to the binary content to"      \
-    " disassemble, as a pychrysalide.analysis.BinContent.SourceEndian"  \
-    " value.\n"
-
-
-
 /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
 
 
@@ -308,6 +283,29 @@ static int py_arch_processor_init(PyObject *self, PyObject *args, PyObject *kwds
 
     static char *kwlist[] = { "endianness", NULL };
 
+#define ARCH_PROCESSOR_DOC                                              \
+    "The ArchProcessor object aims to get subclassed to create"         \
+    " processors for new architectures.\n"                              \
+    "\n"                                                                \
+    "Several items have to be defined as class attributes in the final" \
+    " class:\n"                                                         \
+    "* *_key*: a string providing a small name used to identify the"    \
+    " architecture;\n"                                                  \
+    "* *_desc*: a string for a human readable description of the"       \
+    " new architecture;\n"                                              \
+    "* *_memory_size*: size of the memory space, as a"                  \
+    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
+    "* *_ins_min_size*: size of the smallest instruction, as a"         \
+    " pychrysalide.analysis.BinContent.MemoryDataSize value;\n"         \
+    "* *_virtual_space*: a boolean value indicating if the architecture"\
+    " supports a virtual space.\n"                                      \
+    "\n"                                                                \
+    "Calls to the *__init__* constructor of this abstract object expect"\
+    " the following arguments as keyword parameters:\n"                 \
+    "* *endianness*: endianness to apply to the binary content to"      \
+    " disassemble, as a pychrysalide.analysis.BinContent.SourceEndian"  \
+    " value."
+
     /* Récupération des paramètres */
 
     ret = PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &endianness);
diff --git a/plugins/pychrysalide/format/known.c b/plugins/pychrysalide/format/known.c
index e19a4a2..c3b5b9d 100644
--- a/plugins/pychrysalide/format/known.c
+++ b/plugins/pychrysalide/format/known.c
@@ -28,19 +28,48 @@
 #include <pygobject.h>
 
 
-#include <format/known.h>
+#include <i18n.h>
+#include <format/known-int.h>
+#include <plugins/dt.h>
 
 
 #include "../access.h"
 #include "../helpers.h"
+#include "../analysis/content.h"
 
 
 
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_known_format_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise la classe des descriptions de fichier binaire. */
+static void py_known_format_init_gclass(GKnownFormatClass *, gpointer);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_known_format_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique la désignation interne du format. */
+static char *py_known_format_get_key_wrapper(const GKnownFormat *);
+
+/* Fournit une description humaine du format. */
+static char *py_known_format_get_description_wrapper(const GKnownFormat *);
+
+/* Assure l'interprétation d'un format en différé. */
+static bool py_known_format_analyze_wrapper(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
+
+
+
+/* --------------------------- DEFINITION DU FORMAT CONNU --------------------------- */
+
+
 /* Assure l'interprétation d'un format en différé. */
 static PyObject *py_known_format_analyze(PyObject *, PyObject *);
 
 /* Indique la désignation interne du format. */
-static PyObject *py_known_format_get_name(PyObject *, void *);
+static PyObject *py_known_format_get_key(PyObject *, void *);
 
 /* Indique la désignation humaine du format. */
 static PyObject *py_known_format_get_description(PyObject *, void *);
@@ -50,9 +79,332 @@ static PyObject *py_known_format_get_content(PyObject *, void *);
 
 
 
-#define KNOWN_FORMAT_DOC                                                                \
-    "KnownFormat is a small class providing basic features for recognized formats."
+/* ---------------------------------------------------------------------------------- */
+/*                          GLUE POUR CREATION DEPUIS PYTHON                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type du nouvel objet à mettre en place.               *
+*                args = éventuelle liste d'arguments.                         *
+*                kwds = éventuel dictionnaire de valeurs mises à disposition. *
+*                                                                             *
+*  Description : Accompagne la création d'une instance dérivée en Python.     *
+*                                                                             *
+*  Retour      : Nouvel objet Python mis en place ou NULL en cas d'échec.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_known_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;                       /* Objet à retourner           */
+    PyTypeObject *base;                     /* Type de base à dériver      */
+    bool first_time;                        /* Evite les multiples passages*/
+    GType gtype;                            /* Nouveau type de processeur  */
+    bool status;                            /* Bilan d'un enregistrement   */
+
+    /* Validations diverses */
+
+    base = get_python_known_format_type();
+
+    if (type == base)
+    {
+        result = NULL;
+        PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+        goto exit;
+    }
+
+    /* Mise en place d'un type dédié */
+
+    first_time = (g_type_from_name(type->tp_name) == 0);
+
+    gtype = build_dynamic_type(G_TYPE_KNOWN_FORMAT, type->tp_name,
+                               (GClassInitFunc)py_known_format_init_gclass, NULL, NULL);
+
+    if (first_time)
+    {
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+
+        if (!status)
+        {
+            result = NULL;
+            goto exit;
+        }
+
+    }
+
+    /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+    result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                unused = données non utilisées ici.                          *
+*                                                                             *
+*  Description : Initialise la classe générique des processeurs.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_known_format_init_gclass(GKnownFormatClass *class, gpointer unused)
+{
+    class->get_key = py_known_format_get_key_wrapper;
+    class->get_desc = py_known_format_get_description_wrapper;
+
+    class->analyze = py_known_format_analyze_wrapper;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_known_format_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GBinContent *content;                   /* Contenu à intégrer au format*/
+    int ret;                                /* Bilan de lecture des args.  */
+    GKnownFormat *format;                   /* Format à manipuler          */
+
+#define KNOWN_FORMAT_DOC                                                \
+    "KnownFormat is a small class providing basic features for"         \
+    " recognized formats.\n"                                            \
+    "\n"                                                                \
+    "One item has to be defined as class attribute in the final"        \
+    " class:\n"                                                         \
+    "* *_key*: a string providing a small name used to identify the"    \
+    " format.\n"                                                        \
+    "\n"                                                                \
+    "The following methods have to be defined for new classes:\n"       \
+    "* pychrysalide.format.KnownFormat._get_description();\n"           \
+    "* pychrysalide.format.KnownFormat._analyze().\n"                   \
+    "\n"                                                                \
+    "Calls to the *__init__* constructor of this abstract object expect"\
+    " only one argument: a binary content, provided as a"               \
+    " pychrysalide.analysis.BinContent instance."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    format = G_KNOWN_FORMAT(pygobject_get(self));
+
+    g_known_format_set_content(format, content);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description du format connu à consulter.            *
+*                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Désignation du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *py_known_format_get_key_wrapper(const GKnownFormat *format)
+{
+    char *result;                           /* Désignation à renvoyer      */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pykey;                        /* Clef en objet Python        */
+    int ret;                                /* Bilan d'une conversion      */
+
+    result = NULL;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(format));
+
+    if (PyObject_HasAttrString(pyobj, "_key"))
+    {
+        pykey = PyObject_GetAttrString(pyobj, "_key");
+
+        if (pykey != NULL)
+        {
+            ret = PyUnicode_Check(pykey);
+
+            if (ret)
+                result = strdup(PyUnicode_AsUTF8(pykey));
+
+            Py_DECREF(pykey);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description du format connu à consulter.            *
+*                                                                             *
+*  Description : Fournit une description humaine du format.                   *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *py_known_format_get_description_wrapper(const GKnownFormat *format)
+{
+    char *result;                           /* Description à retourner     */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pyret;                        /* Bilan de consultation       */
+    int ret;                                /* Bilan d'une conversion      */
+
+#define KNOWN_FORMAT_GET_DESCRIPTION_WRAPPER PYTHON_WRAPPER_DEF     \
+(                                                                   \
+    _get_description, "$self, /",                                   \
+    METH_NOARGS,                                                    \
+    "Abstract method used to build a description of the format.\n"  \
+    "\n"                                                            \
+    "The result is expected to be a string."                        \
+)
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(format));
+
+    if (has_python_method(pyobj, "_get_description"))
+    {
+        pyret = run_python_method(pyobj, "_get_description", NULL);
+
+        if (pyret != NULL)
+        {
+            ret = PyUnicode_Check(pyret);
+
+            if (ret)
+                result = strdup(PyUnicode_AsUTF8(pyret));
+
+            Py_DECREF(pyret);
+
+        }
+
+    }
+
+    PyGILState_Release(gstate);
+
+    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   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *pyret;                        /* Bilan d'exécution           */
+
+#define KNOWN_FORMAT_ANALYZE_WRAPPER PYTHON_WRAPPER_DEF             \
+(                                                                   \
+    _analyze, "$self, gid, status, /",                              \
+    METH_VARARGS,                                                   \
+    "Abstract method used to start the analysis of the known"       \
+    " format and return its status.\n"                              \
+    "\n"                                                            \
+    "The identifier refers to the working queue used to process"    \
+    " the analysis. A reference to the main status bar may also be" \
+    " provided, as a pychrysalide.gtkext.StatusStack instance if"   \
+    " running in graphical mode or None otherwise.\n"               \
+    "\n"                                                            \
+    "The expected result of the call is a boolean."                 \
+)
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
 
+    pyobj = pygobject_new(G_OBJECT(format));
+
+    if (has_python_method(pyobj, "_analyze"))
+    {
+        args = PyTuple_New(2);
+
+        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(gid));
+        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(status)));
+
+        pyret = run_python_method(pyobj, "_analyze", args);
+
+        result = (pyret == Py_True);
+
+        Py_DECREF(args);
+        Py_XDECREF(pyret);
+
+    }
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                             DEFINITION DU FORMAT CONNU                             */
+/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
@@ -75,11 +427,21 @@ static PyObject *py_known_format_analyze(PyObject *self, PyObject *args)
     GKnownFormat *format;                   /* Format connu manipulé       */
     bool status;                            /* Bilan de l'opération        */
 
-#define KNOWN_FORMAT_ANALYZE_METHOD PYTHON_METHOD_DEF                   \
-(                                                                       \
-    analyze, "$self, /, gid, status",                                   \
-    METH_VARARGS, py_known_format,                                      \
-    "Start the analysis of the known format and return its status."     \
+#define KNOWN_FORMAT_ANALYZE_METHOD PYTHON_METHOD_DEF               \
+(                                                                   \
+    analyze, "$self, gid, status, /",                               \
+    METH_VARARGS, py_known_format,                                  \
+    "Start the analysis of the known format and return its status." \
+    "\n"                                                            \
+    "Once this analysis is done, a few early symbols and the"       \
+    " mapped sections are expected to be defined, if any.\n"        \
+    "\n"                                                            \
+    "The identifier refers to the working queue used to process"    \
+    " the analysis. A reference to the main status bar may also be" \
+    " provided, as a pychrysalide.gtkext.StatusStack instance if"   \
+    " running in graphical mode or None otherwise.\n"               \
+    "\n"                                                            \
+    "The return value is a boolean status of the operation."        \
 )
 
     ret = PyArg_ParseTuple(args, "");//|KO!", &gid, &status);
@@ -104,29 +466,31 @@ static PyObject *py_known_format_analyze(PyObject *self, PyObject *args)
 *                                                                             *
 *  Description : Indique la désignation interne du format.                    *
 *                                                                             *
-*  Retour      : Description du format.                                       *
+*  Retour      : Désignation du format.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_known_format_get_name(PyObject *self, void *closure)
+static PyObject *py_known_format_get_key(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Trouvailles à retourner     */
     GKnownFormat *format;                   /* Format de binaire manipulé  */
-    const char *name;                       /* Description interne         */
+    char *key;                              /* Désignation interne         */
 
-#define KNOWN_FORMAT_NAME_ATTRIB PYTHON_GET_DEF_FULL        \
-(                                                           \
-    name, py_known_format,                                  \
-    "Internal name of the known format."                    \
+#define KNOWN_FORMAT_KEY_ATTRIB PYTHON_GET_DEF_FULL                     \
+(                                                                       \
+    key, py_known_format,                                               \
+    "Internal name of the known format, provided as a (tiny) string."   \
 )
 
     format = G_KNOWN_FORMAT(pygobject_get(self));
 
-    name = g_known_format_get_name(format);
+    key = g_known_format_get_key(format);
+
+    result = PyUnicode_FromString(key);
 
-    result = PyUnicode_FromString(name);
+    free(key);
 
     return result;
 
@@ -150,12 +514,12 @@ static PyObject *py_known_format_get_description(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Trouvailles à retourner     */
     GKnownFormat *format;                   /* Format de binaire manipulé  */
-    const char *desc;                       /* Description humaine         */
+    char *desc;                             /* Description humaine         */
 
 #define KNOWN_FORMAT_DESCRIPTION_ATTRIB PYTHON_GET_DEF_FULL     \
 (                                                               \
     description, py_known_format,                               \
-    "Human description of the known format."                    \
+    "Human description of the known format, as a string."       \
 )
 
     format = G_KNOWN_FORMAT(pygobject_get(self));
@@ -164,6 +528,8 @@ static PyObject *py_known_format_get_description(PyObject *self, void *closure)
 
     result = PyUnicode_FromString(desc);
 
+    free(desc);
+
     return result;
 
 }
@@ -188,10 +554,12 @@ static PyObject *py_known_format_get_content(PyObject *self, void *closure)
     GKnownFormat *format;                   /* Format de binaire manipulé  */
     GBinContent *content;                   /* Instance GLib correspondante*/
 
-#define KNOWN_FORMAT_CONTENT_ATTRIB PYTHON_GET_DEF_FULL     \
-(                                                           \
-    content, py_known_format,                               \
-    "Binary content linked to the known format."            \
+#define KNOWN_FORMAT_CONTENT_ATTRIB PYTHON_GET_DEF_FULL             \
+(                                                                   \
+    content, py_known_format,                                       \
+    "Binary content linked to the known format."                    \
+    "\n"                                                            \
+    "The result is a pychrysalide.analysis.BinContent instance."    \
 )
 
     format = G_KNOWN_FORMAT(pygobject_get(self));
@@ -222,12 +590,14 @@ static PyObject *py_known_format_get_content(PyObject *self, void *closure)
 PyTypeObject *get_python_known_format_type(void)
 {
     static PyMethodDef py_known_format_methods[] = {
+        KNOWN_FORMAT_GET_DESCRIPTION_WRAPPER,
+        KNOWN_FORMAT_ANALYZE_WRAPPER,
         KNOWN_FORMAT_ANALYZE_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_known_format_getseters[] = {
-        KNOWN_FORMAT_NAME_ATTRIB,
+        KNOWN_FORMAT_KEY_ATTRIB,
         KNOWN_FORMAT_DESCRIPTION_ATTRIB,
         KNOWN_FORMAT_CONTENT_ATTRIB,
         { NULL }
@@ -245,7 +615,10 @@ PyTypeObject *get_python_known_format_type(void)
         .tp_doc         = KNOWN_FORMAT_DOC,
 
         .tp_methods     = py_known_format_methods,
-        .tp_getset      = py_known_format_getseters
+        .tp_getset      = py_known_format_getseters,
+
+        .tp_init        = py_known_format_init,
+        .tp_new         = py_known_format_new,
 
     };
 
@@ -278,8 +651,6 @@ bool ensure_python_known_format_is_registered(void)
     {
         module = get_access_to_python_module("pychrysalide.format");
 
-        APPLY_ABSTRACT_FLAG(type);
-
         dict = PyModule_GetDict(module);
 
         if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_FORMAT, type, &PyGObject_Type))
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index 0d24f8c..208c46a 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -676,6 +676,7 @@ static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *
 
 static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
+    bool result;                            /* Bilan à retourner           */
     PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
     PyObject *pyobj;                        /* Objet Python concerné       */
     PyObject *args;                         /* Arguments pour l'appel      */
@@ -701,6 +702,8 @@ static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPlugin
     " *FORMAT_POST_ANALYSIS_STARTED* or *FORMAT_POST_ANALYSIS_ENDED*."              \
 )
 
+    result = false;
+
     gstate = PyGILState_Ensure();
 
     pyobj = pygobject_new(G_OBJECT(plugin));
@@ -716,6 +719,8 @@ static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPlugin
 
         pyret = run_python_method(pyobj, "_handle_format_analysis", args);
 
+        result = (pyret == Py_True);
+
         Py_XDECREF(pyret);
         Py_DECREF(args);
 
@@ -725,7 +730,7 @@ static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPlugin
 
     PyGILState_Release(gstate);
 
-    return true;
+    return result;
 
 }
 
diff --git a/src/format/known-int.h b/src/format/known-int.h
index e4d3bd6..7b79e50 100644
--- a/src/format/known-int.h
+++ b/src/format/known-int.h
@@ -30,10 +30,10 @@
 
 
 /* Indique la désignation interne du format. */
-typedef const char * (* known_get_name_fc) (const GKnownFormat *);
+typedef char * (* known_get_key_fc) (const GKnownFormat *);
 
 /* Fournit une description humaine du format. */
-typedef const char * (* known_get_desc_fc) (const GKnownFormat *);
+typedef char * (* known_get_desc_fc) (const GKnownFormat *);
 
 /*Assure l'interprétation d'un format en différé. */
 typedef bool (* known_analyze_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *);
@@ -53,7 +53,7 @@ struct _GKnownFormatClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    known_get_name_fc get_name;             /* Désignation interne         */
+    known_get_key_fc get_key;               /* Désignation interne         */
     known_get_desc_fc get_desc;             /* Désignation humaine         */
 
     known_analyze_fc analyze;               /* Interprétation du format    */
diff --git a/src/format/known.c b/src/format/known.c
index 9a3eef6..c1850bc 100644
--- a/src/format/known.c
+++ b/src/format/known.c
@@ -135,7 +135,7 @@ static void g_known_format_finalize(GKnownFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = description de l'exécutable à consulter.           *
+*  Paramètres  : format = description du format connu à consulter.            *
 *                content = contenu binaire à parcourir.                       *
 *                                                                             *
 *  Description : Définit le contenu binaire à analyser.                       *
@@ -159,7 +159,7 @@ void g_known_format_set_content(GKnownFormat *format, GBinContent *content)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
+*  Paramètres  : format = description du format connu à consulter.            *
 *                                                                             *
 *  Description : Fournit une référence vers le contenu binaire analysé.       *
 *                                                                             *
@@ -184,21 +184,21 @@ GBinContent *g_known_format_get_content(const GKnownFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
+*  Paramètres  : format = description du format connu à consulter.            *
 *                                                                             *
 *  Description : Indique la désignation interne du format.                    *
 *                                                                             *
-*  Retour      : Description du format.                                       *
+*  Retour      : Désignation du format.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_known_format_get_name(const GKnownFormat *format)
+char *g_known_format_get_key(const GKnownFormat *format)
 {
-    const char *result;                     /* Désignation à retourner     */
+    char *result;                           /* Désignation à retourner     */
 
-    result = G_KNOWN_FORMAT_GET_CLASS(format)->get_name(format);
+    result = G_KNOWN_FORMAT_GET_CLASS(format)->get_key(format);
 
     return result;
 
@@ -207,7 +207,7 @@ const char *g_known_format_get_name(const GKnownFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
+*  Paramètres  : format = description du format connu à consulter.            *
 *                                                                             *
 *  Description : Fournit une description humaine du format.                   *
 *                                                                             *
@@ -217,9 +217,9 @@ const char *g_known_format_get_name(const GKnownFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-const char *g_known_format_get_description(const GKnownFormat *format)
+char *g_known_format_get_description(const GKnownFormat *format)
 {
-    const char *result;                     /* Désignation à retourner     */
+    char *result;                           /* Description à retourner     */
 
     result = G_KNOWN_FORMAT_GET_CLASS(format)->get_desc(format);
 
diff --git a/src/format/known.h b/src/format/known.h
index c89ba4a..2d30147 100644
--- a/src/format/known.h
+++ b/src/format/known.h
@@ -59,10 +59,10 @@ void g_known_format_set_content(GKnownFormat *, GBinContent *);
 GBinContent *g_known_format_get_content(const GKnownFormat *);
 
 /* Indique la désignation interne du format. */
-const char *g_known_format_get_name(const GKnownFormat *);
+char *g_known_format_get_key(const GKnownFormat *);
 
 /* Fournit une description humaine du format. */
-const char *g_known_format_get_description(const GKnownFormat *);
+char *g_known_format_get_description(const GKnownFormat *);
 
 /* Assure l'interprétation d'un format en différé. */
 bool g_known_format_analyze(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
diff --git a/tests/format/known.py b/tests/format/known.py
new file mode 100644
index 0000000..056238f
--- /dev/null
+++ b/tests/format/known.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.format import KnownFormat
+
+
+class TestKnownFormat(ChrysalideTestCase):
+    """TestCase for format.KnownFormat."""
+
+
+    def testKnownFormatConstructor(self):
+        """Build Load a simple content for a flat format."""
+
+        with self.assertRaisesRegex(RuntimeError, 'pychrysalide.format.KnownFormat is an abstract class'):
+            fmt = KnownFormat()
+
+        class MyKnownFormat(KnownFormat):
+            pass
+
+        with self.assertRaisesRegex(TypeError, 'function takes exactly 1 argument .0 given.'):
+            fmt = MyKnownFormat()
+
+        class MyKnownFormat2(KnownFormat):
+            pass
+
+        with self.assertRaisesRegex(TypeError, 'unable to convert the provided argument to binary content'):
+            fmt = MyKnownFormat2(123)
+
+        class MyKnownFormatReady(KnownFormat):
+            _key = 'rdy'
+            def __init2__(self, cnt):
+                super(MyKnownFormatReady, self).__init2__(cnt)
+
+        data  = b'\x00\x00\x00\xef'
+
+        cnt = MemoryContent(data)
+        fmt = MyKnownFormatReady(cnt)
+
+        self.assertIsNotNone(fmt)
+
+        self.assertEqual(fmt.key, 'rdy')
-- 
cgit v0.11.2-87-g4458