summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/plugin.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-01-16 19:02:56 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-01-16 19:02:56 (GMT)
commit9da8f8b37e3edebc917b4e223dd2447cd7cbc818 (patch)
tree3f330b13e7ca2a0a163882be3043ca9571f25211 /plugins/pychrysalide/plugin.c
parenteb9b7fd76451db5c9f07a800c0394480e4b88c9c (diff)
Changed the Python bindings source directory and updated code.
Diffstat (limited to 'plugins/pychrysalide/plugin.c')
-rw-r--r--plugins/pychrysalide/plugin.c809
1 files changed, 809 insertions, 0 deletions
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
new file mode 100644
index 0000000..fad0084
--- /dev/null
+++ b/plugins/pychrysalide/plugin.c
@@ -0,0 +1,809 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plugin.c - interactions avec un greffon Python
+ *
+ * Copyright (C) 2012-2017 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 "plugin.h"
+
+
+#include <pygobject.h>
+#include <string.h>
+
+
+#include <common/extstr.h>
+#include "../../src/core/formats.h"
+//#include <core/formats.h>
+#include <plugins/plugin-int.h>
+
+
+#include "helpers.h"
+
+
+
+/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
+
+
+/* Ligne de représentation de code binaire (instance) */
+struct _GPythonPlugin
+{
+ GPluginModule parent; /* Instance parente */
+
+ PyObject *module; /* Script Python chargé */
+ PyObject *instance; /* Instance Python du greffon */
+
+};
+
+
+/* Ligne de représentation de code binaire (classe) */
+struct _GPythonPluginClass
+{
+ GPluginModuleClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des greffons Python. */
+static void g_python_plugin_class_init(GPythonPluginClass *);
+
+/* Initialise l'instance d'un greffon Python. */
+static void g_python_plugin_init(GPythonPlugin *);
+
+/* Reconstruit la déclaration d'interface à partir de lectures. */
+static bool g_python_plugin_read_interface(GPythonPlugin *);
+
+/* Procède à l'initialisation du greffon. */
+static bool g_python_plugin_do_init(GPythonPlugin *);
+
+/* Procède à l'extinction du greffon. */
+static bool g_python_plugin_do_exit(GPythonPlugin *, GObject *);
+
+/* Indique si le format peut être pris en charge ici. */
+FormatMatchStatus python_plugin_is_matching(GBinContent *, GExeFormat *, GPythonPlugin *, char **);
+
+/* Exécute une action pendant un désassemblage de binaire. */
+static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *);
+
+
+
+/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
+
+
+/* Définit les constantes pour les greffons en Python. */
+static bool py_plugin_module_define_constants(PyTypeObject *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE INTERNE POUR GREFFONS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type définit par la GLib pour le greffon Python. */
+G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des greffons Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_class_init(GPythonPluginClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser. *
+* *
+* Description : Initialise l'instance d'un greffon Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_init(GPythonPlugin *plugin)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modname = nom du module à charger. *
+* filename = chemin d'accès au code Python à charger. *
+* *
+* Description : Crée un greffon à partir de code Python. *
+* *
+* Retour : Adresse de la structure mise en place ou NULL si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
+{
+ GPythonPlugin *result; /* Structure à retourner */
+ PyObject *name; /* Chemin d'accès pour Python */
+ PyObject *module; /* Script Python chargé */
+ PyObject *err_type; /* Type d'erreur Python */
+ PyObject *err_value; /* Instance Python d'erreur */
+ PyObject *err_traceback; /* Trace Python associée */
+ PyObject *err_string; /* Description Python d'erreur */
+ const char *err_msg; /* Représentation humaine */
+ PyObject *dict; /* Dictionnaire associé */
+ PyObject *class; /* Classe à instancier */
+ PyObject *instance; /* Instance Python du greffon */
+ size_t i; /* Boucle de parcours */
+ uint32_t action; /* Identifiant d'une action */
+ uint32_t category; /* Catégorie principale */
+ uint32_t sub; /* Sous-catégorie visée */
+
+ name = PyUnicode_FromString(modname);
+ if (name == NULL) goto gppn_bad_exit;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+
+ if (err_value == NULL)
+ log_variadic_message(LMT_ERROR,
+ _("An unknown error occured when importing '%s'..."), modname);
+ else
+ {
+ err_string = PyObject_Str(err_value);
+ err_msg = PyUnicode_AsUTF8(err_string);
+
+ log_variadic_message(LMT_ERROR,
+ _("An error occured when importing '%s': \"%s\""), modname, err_msg);
+
+ Py_DECREF(err_string);
+ Py_DECREF(err_value);
+
+ }
+
+ Py_XDECREF(err_traceback);
+ Py_XDECREF(err_type);
+
+ Py_XDECREF(module);
+
+ module = NULL;
+
+ }
+
+ if (module == NULL) goto gppn_bad_exit;
+
+ dict = PyModule_GetDict(module);
+ class = PyDict_GetItemString(dict, "AutoLoad");
+
+ if (class == NULL) goto gppn_no_class;
+ if (!PyType_Check(class->ob_type)) goto gppn_no_class;
+
+ instance = PyObject_CallFunction(class, NULL);
+ if (instance == NULL) goto gppn_no_instance;
+
+ result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL);
+
+ G_PLUGIN_MODULE(result)->filename = strdup(filename);
+
+ result->module = module;
+ result->instance = instance;
+
+ if (!g_python_plugin_read_interface(result))
+ {
+ printf("bad interface------------\n");
+ goto gppn_interface_error;
+ }
+
+ /* Localisation des différents points d'entrée déclarés */
+
+#define register_python_binding(inst, sym, binding) \
+ ({ \
+ bool __result; \
+ if (!has_python_method(inst, #sym)) \
+ { \
+ log_variadic_message(LMT_ERROR, \
+ _("No '%s' entry in plugin candidate '%s'"), \
+ #sym, G_PLUGIN_MODULE(result)->filename); \
+ __result = false; \
+ } \
+ else \
+ { \
+ G_PLUGIN_MODULE(result)->sym = binding; \
+ __result = true; \
+ } \
+ __result; \
+ })
+
+ for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++)
+ {
+ action = G_PLUGIN_MODULE(result)->interface->actions[i];
+ category = MASK_PLUGIN_CATEGORY(action);
+ sub = MASK_PLUGIN_SUB_CATEGORY(action);
+
+ switch (category)
+ {
+ case DPC_BASIC:
+
+ switch (sub)
+ {
+ case DPS_NONE:
+ break;
+
+ case PGA_PLUGIN_INIT:
+ if (!register_python_binding(instance, init, (pg_management_fc)g_python_plugin_do_init))
+ goto gppn_bad_plugin;
+ break;
+
+ case PGA_PLUGIN_EXIT:
+ if (!register_python_binding(instance, exit, (pg_management_fc)g_python_plugin_do_exit))
+ goto gppn_bad_plugin;
+ break;
+
+ default:
+ log_variadic_message(LMT_WARNING,
+ _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ break;
+
+ }
+
+ break;
+
+ case DPC_BINARY_PROCESSING:
+
+ switch (sub)
+ {
+ case DPS_FORMAT:
+
+ switch (action)
+ {
+ case PGA_FORMAT_MATCHER:
+
+ if (!has_python_method(instance, "is_format_matching"))
+ {
+ log_variadic_message(LMT_ERROR,
+ _("No '%s' entry in plugin candidate '%s'"),
+ "is_format_matching",
+ G_PLUGIN_MODULE(result)->filename);
+ goto gppn_bad_plugin;
+ }
+
+ if (!register_format_matcher((format_match_fc)python_plugin_is_matching, result))
+ goto gppn_bad_plugin;
+
+ break;
+
+ case PGA_FORMAT_LOADER_LAST:
+ /* TODO */
+ break;
+
+ default:
+ log_variadic_message(LMT_WARNING,
+ _("Unknown action '0x%02x' in plugin '%s'..."),
+ action, filename);
+ break;
+
+ }
+
+ break;
+
+ case DPS_DISASSEMBLY:
+ if (!register_python_binding(instance, process_disass,
+ (pg_process_disassembly_fc)g_python_plugin_process_disass))
+ goto gppn_bad_plugin;
+ break;
+
+ default:
+ log_variadic_message(LMT_WARNING,
+ _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ break;
+
+ }
+
+ break;
+
+ default:
+ log_variadic_message(LMT_WARNING,
+ _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
+ break;
+
+ }
+
+ }
+
+ /* Conclusion */
+
+ /*
+ if (!g_plugin_module_load(G_PLUGIN_MODULE(result)))
+ goto gppn_bad_plugin;
+ */
+
+ return G_PLUGIN_MODULE(result);
+
+ gppn_bad_plugin:
+
+ gppn_interface_error:
+
+ g_object_unref(G_OBJECT(result));
+
+ //Py_DECREF(instance);
+
+ gppn_no_instance:
+
+ gppn_no_class:
+
+ //Py_DECREF(module);
+
+ gppn_bad_exit:
+
+ printf("bad exit :(\n");
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à initialiser. *
+* *
+* Description : Reconstruit la déclaration d'interface à partir de lectures. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_python_plugin_read_interface(GPythonPlugin *plugin)
+{
+ bool result; /* Bilan à renvoyer */
+ plugin_interface interface; /* Recueil des éléments */
+ PyObject *desc; /* Tableau de description */
+ PyObject *str; /* Chaîne de caractères */
+ PyObject *tuple; /* Liste d'éléments à traiter */
+ Py_ssize_t count; /* Nombre d'éléments présents */
+ Py_ssize_t i; /* Boucle de parcours */
+ PyObject *action; /* Identifiant d'une action */
+ plugin_interface *final; /* Interface finale conservée */
+
+ result = true;
+
+ desc = run_python_method(plugin->instance, "get_interface", NULL);
+ if (!PyDict_Check(desc))
+ {
+ result = false;
+ goto pgpri_end;
+ }
+
+ memset(&interface, 0, sizeof(interface));
+
+ /* Chargements des premières chaînes */
+
+#define READ_STR_FIELD(name) \
+ str = PyDict_GetItemString(desc, #name); \
+ if ((result = PyUnicode_Check(str))) \
+ interface.name = strdup(PyUnicode_DATA(str)); \
+
+ READ_STR_FIELD(name);
+ READ_STR_FIELD(desc);
+ READ_STR_FIELD(version);
+
+ /* Chargement des actions supportées */
+
+ tuple = PyDict_GetItemString(desc, "actions");
+
+ if (!PyList_Check(tuple))
+ {
+ result = false;
+ goto pgpri_failed;
+ }
+
+ count = PyList_GET_SIZE(tuple);
+
+ interface.actions = (plugin_action_t *)calloc(count, sizeof(plugin_action_t));
+ interface.actions_count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ action = PyList_GET_ITEM(tuple, i);
+
+ interface.actions[i] = PyLong_AsLong(action);
+
+ }
+
+ pgpri_failed:
+
+ if (result)
+ {
+ final = (plugin_interface *)calloc(1, sizeof(plugin_interface));
+
+ memcpy(final, &interface, sizeof(interface));
+
+ G_PLUGIN_MODULE(plugin)->interface = final;
+
+ }
+ else
+ {
+ if (interface.name != NULL) free((char *)interface.name);
+ if (interface.desc != NULL) free((char *)interface.desc);
+ if (interface.version != NULL) free((char *)interface.version);
+
+ if (interface.actions != NULL) free(interface.actions);
+
+ }
+
+ pgpri_end:
+
+ Py_XDECREF(desc);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à initialiser. *
+* ref = espace de référencement global. *
+* *
+* Description : Procède à l'initialisation du greffon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_python_plugin_do_init(GPythonPlugin *plugin)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *value; /* Valeur obtenue */
+
+ args = Py_None;
+ Py_INCREF(args);
+
+ value = run_python_method(plugin->instance, "init", args);
+
+ result = (value != NULL && PyObject_IsTrue(value));
+
+ Py_XDECREF(value);
+ Py_DECREF(args);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à initialiser. *
+* ref = espace de référencement global. *
+* *
+* Description : Procède à l'extinction du greffon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *value; /* Valeur obtenue */
+
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(ref));
+
+ value = run_python_method(plugin->instance, "exit", args);
+
+ result = PyObject_IsTrue(value);
+
+ Py_XDECREF(value);
+ Py_DECREF(args);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à parcourir. *
+* parent = éventuel format exécutable déjà chargé. *
+* plugin = grefon C interne représentant le grefon Python. *
+* 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 python_plugin_is_matching(GBinContent *content, GExeFormat *parent, GPythonPlugin *plugin, char **key)
+{
+ FormatMatchStatus result; /* Bilan à renvoyer */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *value; /* Valeur obtenue */
+ PyObject *arg; /* Argument en élément de tuple*/
+
+ result = FMS_UNKNOWN;
+
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(content)));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(parent)));
+
+ value = run_python_method(plugin->instance, "is_format_matching", args);
+
+ if (PyTuple_Check(value))
+ {
+ if (PyTuple_Size(value) > 0)
+ {
+ arg = PyTuple_GetItem(value, 0);
+
+ if (PyLong_Check(arg))
+ {
+ result = PyLong_AsLong(arg);
+
+ switch (result)
+ {
+ case FMS_MATCHED:
+
+ if (PyTuple_Size(value) != 2)
+ {
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+ _("Expecting only a tuple [ status, key ] " \
+ "as result for format matching."));
+ result = FMS_UNKNOWN;
+ break;
+ }
+
+ arg = PyTuple_GetItem(value, 1);
+
+ if (PyUnicode_Check(arg))
+ *key = strdup(PyUnicode_AsUTF8(arg));
+
+ else
+ {
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+ _("Expecting a key string for format matching."));
+ result = FMS_UNKNOWN;
+ }
+
+ break;
+
+ case FMS_FORWARDED:
+ case FMS_UNKNOWN:
+ if (PyTuple_Size(value) != 1)
+ {
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING,
+ _("Unused second item for format matching."));
+ }
+ break;
+
+ default:
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+ _("Unexpected result for format matching."));
+ result = FMS_UNKNOWN;
+ break;
+
+ }
+
+ }
+
+ else
+ {
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+ _("Unexpected result status for format matching."));
+ result = FMS_UNKNOWN;
+ }
+
+ }
+ else
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING,
+ _("Interpreting a empty tuple as FMS_UNKNOWN " \
+ "for format matching."));
+
+ }
+ else
+ g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+ _("Expected a tuple containing [ status, key ] as result " \
+ "for format matching."));
+
+ Py_XDECREF(value);
+ Py_DECREF(args);
+
+ return result;
+
+
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* binary = binaire dont le contenu est en cours de traitement. *
+* *
+* Description : Exécute une action pendant un désassemblage de binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary)
+{
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *value; /* Valeurs obtenues */
+
+ args = PyTuple_New(2);
+
+ PyTuple_SetItem(args, 0, PyLong_FromLong(action));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary)));
+
+ value = run_python_method(plugin->instance, "process_binary_disassembly", args);
+
+ Py_XDECREF(value);
+ Py_DECREF(args);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MODULE PYTHON POUR LES SCRIPTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : obj_type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes pour les greffons en Python. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_plugin_module_define_constants(PyTypeObject *obj_type)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ 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_FORMAT_MATCHER);
+ result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_LOADER_LAST);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_STARTED);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RAW);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_LINK);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_POST);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LIMITED);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LOOPS);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LINKED);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_GROUPED);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RANKED);
+ result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_ENDED);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_plugin_module_type(void)
+{
+ static PyMethodDef py_plugin_module_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_plugin_module_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_plugin_module_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.PluginModule",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = "Chrysalide plugin for Python.",
+
+ .tp_methods = py_plugin_module_methods,
+ .tp_getset = py_plugin_module_getseters
+
+ };
+
+ return &py_plugin_module_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.PluginModule'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_plugin_module(PyObject *module)
+{
+ PyTypeObject *py_plugin_module_type; /* Type Python 'PluginModule' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ py_plugin_module_type = get_python_plugin_module_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, py_plugin_module_type, &PyGObject_Type))
+ return false;
+
+ if (!py_plugin_module_define_constants(py_plugin_module_type))
+ return false;
+
+ return true;
+
+}