From c4d2e0fa48eab453d5c43a3c0938427617449a6a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 6 Apr 2021 23:46:59 +0200
Subject: Inject known names for PE imports by ordinals.

---
 configure.ac                           |   2 +
 plugins/Makefile.am                    |   1 +
 plugins/devdbg/speed.c                 |   2 +-
 plugins/winordinals/Makefile.am        |  54 ++++
 plugins/winordinals/assign.c           | 348 +++++++++++++++++++++++++
 plugins/winordinals/assign.h           |  38 +++
 plugins/winordinals/cache_oleaut32.c   | 458 +++++++++++++++++++++++++++++++++
 plugins/winordinals/cache_oleaut32.h   |  37 +++
 plugins/winordinals/cache_ws2_32.c     | 260 +++++++++++++++++++
 plugins/winordinals/cache_ws2_32.h     |  37 +++
 plugins/winordinals/cache_wsock32.c    | 137 ++++++++++
 plugins/winordinals/cache_wsock32.h    |  37 +++
 plugins/winordinals/core.c             | 110 ++++++++
 plugins/winordinals/core.h             |  41 +++
 plugins/winordinals/ordinals.c         | 109 ++++++++
 plugins/winordinals/ordinals.h         |  40 +++
 plugins/winordinals/python/Makefile.am |  18 ++
 plugins/winordinals/python/module.c    | 112 ++++++++
 plugins/winordinals/python/module.h    |  41 +++
 tools/ordinals/cache-pe-exports.py     | 218 ++++++++++++++++
 20 files changed, 2099 insertions(+), 1 deletion(-)
 create mode 100644 plugins/winordinals/Makefile.am
 create mode 100644 plugins/winordinals/assign.c
 create mode 100644 plugins/winordinals/assign.h
 create mode 100644 plugins/winordinals/cache_oleaut32.c
 create mode 100644 plugins/winordinals/cache_oleaut32.h
 create mode 100644 plugins/winordinals/cache_ws2_32.c
 create mode 100644 plugins/winordinals/cache_ws2_32.h
 create mode 100644 plugins/winordinals/cache_wsock32.c
 create mode 100644 plugins/winordinals/cache_wsock32.h
 create mode 100644 plugins/winordinals/core.c
 create mode 100644 plugins/winordinals/core.h
 create mode 100644 plugins/winordinals/ordinals.c
 create mode 100644 plugins/winordinals/ordinals.h
 create mode 100644 plugins/winordinals/python/Makefile.am
 create mode 100644 plugins/winordinals/python/module.c
 create mode 100644 plugins/winordinals/python/module.h
 create mode 100644 tools/ordinals/cache-pe-exports.py

diff --git a/configure.ac b/configure.ac
index dd463e7..d7a6844 100644
--- a/configure.ac
+++ b/configure.ac
@@ -533,6 +533,8 @@ AC_CONFIG_FILES([Makefile
                  plugins/readelf/Makefile
                  plugins/readmc/Makefile
                  plugins/ropgadgets/Makefile
+                 plugins/winordinals/Makefile
+                 plugins/winordinals/python/Makefile
                  plugins/yaml/Makefile
                  plugins/yaml/python/Makefile
                  src/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index e9258df..4addee5 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -27,4 +27,5 @@ SUBDIRS = \
 	readelf \
 	readmc \
 	ropgadgets \
+	winordinals \
 	yaml
diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c
index c643a91..e34e84f 100644
--- a/plugins/devdbg/speed.c
+++ b/plugins/devdbg/speed.c
@@ -40,7 +40,7 @@
 
 DEFINE_CHRYSALIDE_PLUGIN("SpeedMeasure", "Tracker of time spent for disassembling code",
                          PACKAGE_VERSION, CHRYSALIDE_WEBSITE(""),
-                         NO_REQ, AL(PGA_FORMAT_ANALYSIS_STARTED,PGA_FORMAT_ANALYSIS_ENDED,
+                         NO_REQ, AL(PGA_FORMAT_ANALYSIS_STARTED, PGA_FORMAT_ANALYSIS_ENDED,
                                     PGA_FORMAT_POST_ANALYSIS_STARTED, PGA_FORMAT_POST_ANALYSIS_ENDED,
                                     PGA_DISASSEMBLY_STARTED, PGA_DISASSEMBLY_ENDED));
 
diff --git a/plugins/winordinals/Makefile.am b/plugins/winordinals/Makefile.am
new file mode 100644
index 0000000..91607f3
--- /dev/null
+++ b/plugins/winordinals/Makefile.am
@@ -0,0 +1,54 @@
+
+lib_LTLIBRARIES = libwinordinals.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD =							\
+	python/libwinordinalspython.la
+
+if BUILD_DISCARD_LOCAL
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(pluginslibdir) \
+					-L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+else
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \
+					-L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+endif
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libwinordinals_la_SOURCES =					\
+	assign.h assign.c						\
+	cache_oleaut32.h cache_oleaut32.c		\
+	cache_ws2_32.h cache_ws2_32.c			\
+	cache_wsock32.h cache_wsock32.c			\
+	core.h core.c							\
+	ordinals.h ordinals.c
+
+libwinordinals_la_LIBADD =					\
+	$(PYTHON3_LIBADD)
+
+libwinordinals_la_LDFLAGS =					\
+	-L$(top_srcdir)/src/.libs -lchrysacore	\
+	$(PYTHON3_LDFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libwinordinals_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/winordinals/assign.c b/plugins/winordinals/assign.c
new file mode 100644
index 0000000..16b7eaa
--- /dev/null
+++ b/plugins/winordinals/assign.c
@@ -0,0 +1,348 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * assign.c - renseignement des importations sous forme d'ordinaux
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "assign.h"
+
+
+#include <i18n.h>
+#include <core/global.h>
+#include <core/nproc.h>
+#include <glibext/delayed-int.h>
+#include <plugins/pe/routine.h>
+
+
+#include "ordinals.h"
+
+
+
+#define G_TYPE_ORDINAL_RESOLVER            g_ordinal_resolver_get_type()
+#define G_ORDINAL_RESOLVER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolver))
+#define G_IS_ORDINAL_RESOLVER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ORDINAL_RESOLVER))
+#define G_ORDINAL_RESOLVER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolverClass))
+#define G_IS_ORDINAL_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ORDINAL_RESOLVER))
+#define G_ORDINAL_RESOLVER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolverClass))
+
+
+/* Tâche de résolution d'ordinaux (instance) */
+typedef struct _GOrdinalResolver
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    GPeFormat *format;                      /* Format à faire évoluer      */
+
+    size_t begin;                           /* Point de départ du parcours */
+    size_t end;                             /* Point d'arrivée exclu       */
+
+    activity_id_t id;                       /* Identifiant pour messages   */
+
+} GOrdinalResolver;
+
+/* Tâche de résolution d'ordinaux (classe) */
+typedef struct _GOrdinalResolverClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+} GOrdinalResolverClass;
+
+
+/* Indique le type défini pour les tâches de résolution d'ordinaux. */
+GType g_ordinal_resolver_get_type(void);
+
+/* Initialise la classe des tâches des resolutions d'ordinaux. */
+static void g_ordinal_resolver_class_init(GOrdinalResolverClass *);
+
+/* Initialise une tâche de résolution d'ordinaux importés. */
+static void g_ordinal_resolver_init(GOrdinalResolver *);
+
+/* Supprime toutes les références externes. */
+static void g_ordinal_resolver_dispose(GOrdinalResolver *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_ordinal_resolver_finalize(GOrdinalResolver *);
+
+/* Crée une tâche de résolution des ordinaux importés. */
+static GOrdinalResolver *g_ordinal_resolver_new(GPeFormat *, size_t, size_t, activity_id_t);
+
+/* Effectue une résolution d'ordinaux importés. */
+static void g_ordinal_resolver_process(GOrdinalResolver *, GtkStatusStack *);
+
+
+
+/* Indique le type défini pour les tâches de résolution d'ordinaux. */
+G_DEFINE_TYPE(GOrdinalResolver, g_ordinal_resolver, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches des resolutions d'ordinaux.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_ordinal_resolver_class_init(GOrdinalResolverClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_ordinal_resolver_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_ordinal_resolver_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_ordinal_resolver_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une tâche de résolution d'ordinaux importés.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_ordinal_resolver_init(GOrdinalResolver *resolver)
+{
+    resolver->format = NULL;
+
+    resolver->begin = 0;
+    resolver->end = 0;
+
+    resolver->id = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_ordinal_resolver_dispose(GOrdinalResolver *resolver)
+{
+    g_clear_object(&resolver->format);
+
+    G_OBJECT_CLASS(g_ordinal_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_ordinal_resolver_finalize(GOrdinalResolver *resolver)
+{
+    G_OBJECT_CLASS(g_ordinal_resolver_parent_class)->finalize(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = ensemble d'instructions désassemblées.              *
+*                begin  = point de départ du parcours de liste.               *
+*                end    = point d'arrivée exclu du parcours.                  *
+*                id     = identifiant du message affiché à l'utilisateur.     *
+*                                                                             *
+*  Description : Crée une tâche de résolution des ordinaux importés.          *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GOrdinalResolver *g_ordinal_resolver_new(GPeFormat *format, size_t begin, size_t end, activity_id_t id)
+{
+    GOrdinalResolver *result;               /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_ORDINAL_RESOLVER, NULL);
+
+    result->format = format;
+    g_object_ref(G_OBJECT(format));
+
+    result->begin = begin;
+    result->end = end;
+
+    result->id = id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : resolver = étude de routines à mener.                        *
+*                status   = barre de statut à tenir informée.                 *
+*                                                                             *
+*  Description : Effectue une résolution d'ordinaux importés.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_ordinal_resolver_process(GOrdinalResolver *resolver, GtkStatusStack *status)
+{
+    GBinFormat *base;                       /* Format basique du binaire   */
+    size_t i;                               /* Boucle de parcours #1       */
+    GBinSymbol *symbol;                     /* Commodité d'accès           */
+    uint16_t ordinal;                       /* Ordinal défini              */
+    const char *name;                       /* Désignation actuelle        */
+    const char *library;                    /* Fichier DLL à charger       */
+
+    base = G_BIN_FORMAT(resolver->format);
+
+    for (i = resolver->begin; i < resolver->end; i++)
+    {
+        symbol = g_binary_format_get_symbol(base, i);
+
+        if (!G_IS_PE_IMPORTED_ROUTINE(symbol))
+            goto next;
+
+        ordinal = g_pe_exported_routine_get_ordinal(G_PE_EXPORTED_ROUTINE(symbol));
+
+        if (ordinal == UNDEF_PE_ORDINAL)
+            goto next;
+
+        name = g_binary_routine_get_name(G_BIN_ROUTINE(symbol));
+
+        if (name != NULL)
+            goto next;
+
+        library = g_pe_imported_routine_get_library(G_PE_IMPORTED_ROUTINE(symbol));
+
+        if (library == NULL)
+            goto next;
+
+        name = get_symbol_by_ordinal(library, ordinal);
+
+        if (name != NULL)
+            g_binary_routine_set_name(G_BIN_ROUTINE(symbol), strdup(name));
+
+ next:
+
+        gtk_status_stack_update_activity_value(status, resolver->id, 1);
+
+        g_object_unref(G_OBJECT(symbol));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format PE à traiter.                                *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Attribue un nom aux symboles PE importés par ordinal.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void assign_name_imported_ordinals(GPeFormat *format, GtkStatusStack *status)
+{
+    GBinFormat *base;                       /* Format basique du binaire   */
+    size_t sym_count;                       /* Nombre de ces symboles      */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    size_t run_size;                        /* Volume réparti par exécution*/
+    activity_id_t id;                       /* Identifiant de progression  */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+    guint i;                                /* Boucle de parcours          */
+    size_t begin;                           /* Début de bloc de traitement */
+    size_t end;                             /* Fin d'un bloc de traitement */
+    GOrdinalResolver *resolver;             /* Tâche d'étude à programmer  */
+
+    base = G_BIN_FORMAT(format);
+
+    g_binary_format_lock_symbols_rd(base);
+
+    sym_count = g_binary_format_count_symbols(base);
+
+    run_size = compute_run_size(sym_count, &runs_count);
+
+    id = gtk_status_stack_add_activity(status, _("Resolving names for imported ordinals..."), sym_count);
+
+    queue = get_work_queue();
+
+    gid = g_work_queue_define_work_group(queue);
+
+    for (i = 0; i < runs_count; i++)
+    {
+        begin = i * run_size;
+
+        if ((i + 1) == runs_count)
+            end = sym_count;
+        else
+            end = begin + run_size;
+
+        resolver = g_ordinal_resolver_new(format, begin, end, id);
+
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(resolver), gid);
+
+    }
+
+    g_work_queue_wait_for_completion(queue, gid);
+
+    g_work_queue_delete_work_group(queue, gid);
+
+    gtk_status_stack_remove_activity(status, id);
+
+    g_binary_format_unlock_symbols_rd(base);
+
+}
diff --git a/plugins/winordinals/assign.h b/plugins/winordinals/assign.h
new file mode 100644
index 0000000..20310d2
--- /dev/null
+++ b/plugins/winordinals/assign.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * assign.h - prototypes pour le renseignement des importations sous forme d'ordinaux
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_ASSIGN_H
+#define _PLUGINS_WINORDINALS_ASSIGN_H
+
+
+#include <gtkext/gtkstatusstack.h>
+#include <plugins/pe/format.h>
+
+
+
+/* Attribue un nom aux symboles PE importés par ordinal. */
+void assign_name_imported_ordinals(GPeFormat *, GtkStatusStack *);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_ASSIGN_H */
diff --git a/plugins/winordinals/cache_oleaut32.c b/plugins/winordinals/cache_oleaut32.c
new file mode 100644
index 0000000..aec923c
--- /dev/null
+++ b/plugins/winordinals/cache_oleaut32.c
@@ -0,0 +1,458 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_oleaut32.c - fourniture des ordinaux du fichier oleaut32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cache_oleaut32.h"
+
+
+#include <stddef.h>
+
+
+
+/**
+ * Empreintes du fichier oleaut32.dll :
+ *
+ *   - MD5 : 9ee967cf9b388c7faaec9f04700eb47b
+ *   - SHA1 : ef5be564b84a7de92b12acbcd69d5f580fabcd89
+ *   - SHA256 : cf34badd43d9e69ca9f01352c4d89c9fd9f4ab53832b1589215a8544462f346d
+ */
+
+
+/* Liste des ordinaux référencés */
+static const char *_oleaut32_ordinals[501] = {
+    [2] = "SysAllocString",
+    [3] = "SysReAllocString",
+    [4] = "SysAllocStringLen",
+    [5] = "SysReAllocStringLen",
+    [6] = "SysFreeString",
+    [7] = "SysStringLen",
+    [8] = "VariantInit",
+    [9] = "VariantClear",
+    [10] = "VariantCopy",
+    [11] = "VariantCopyInd",
+    [12] = "VariantChangeType",
+    [13] = "VariantTimeToDosDateTime",
+    [14] = "DosDateTimeToVariantTime",
+    [15] = "SafeArrayCreate",
+    [16] = "SafeArrayDestroy",
+    [17] = "SafeArrayGetDim",
+    [18] = "SafeArrayGetElemsize",
+    [19] = "SafeArrayGetUBound",
+    [20] = "SafeArrayGetLBound",
+    [21] = "SafeArrayLock",
+    [22] = "SafeArrayUnlock",
+    [23] = "SafeArrayAccessData",
+    [24] = "SafeArrayUnaccessData",
+    [25] = "SafeArrayGetElement",
+    [26] = "SafeArrayPutElement",
+    [27] = "SafeArrayCopy",
+    [28] = "DispGetParam",
+    [29] = "DispGetIDsOfNames",
+    [30] = "DispInvoke",
+    [31] = "CreateDispTypeInfo",
+    [32] = "CreateStdDispatch",
+    [33] = "RegisterActiveObject",
+    [34] = "RevokeActiveObject",
+    [35] = "GetActiveObject",
+    [36] = "SafeArrayAllocDescriptor",
+    [37] = "SafeArrayAllocData",
+    [38] = "SafeArrayDestroyDescriptor",
+    [39] = "SafeArrayDestroyData",
+    [40] = "SafeArrayRedim",
+    [41] = "SafeArrayAllocDescriptorEx",
+    [42] = "SafeArrayCreateEx",
+    [43] = "SafeArrayCreateVectorEx",
+    [44] = "SafeArraySetRecordInfo",
+    [45] = "SafeArrayGetRecordInfo",
+    [47] = "VarNumFromParseNum",
+    [48] = "VarI2FromUI1",
+    [49] = "VarI2FromI4",
+    [50] = "VarI2FromR4",
+    [51] = "VarI2FromR8",
+    [52] = "VarI2FromCy",
+    [53] = "VarI2FromDate",
+    [54] = "VarI2FromStr",
+    [55] = "VarI2FromDisp",
+    [56] = "VarI2FromBool",
+    [57] = "SafeArraySetIID",
+    [58] = "VarI4FromUI1",
+    [59] = "VarI4FromI2",
+    [60] = "VarI4FromR4",
+    [61] = "VarI4FromR8",
+    [62] = "VarI4FromCy",
+    [63] = "VarI4FromDate",
+    [65] = "VarI4FromDisp",
+    [66] = "VarI4FromBool",
+    [67] = "SafeArrayGetIID",
+    [68] = "VarR4FromUI1",
+    [69] = "VarR4FromI2",
+    [70] = "VarR4FromI4",
+    [71] = "VarR4FromR8",
+    [72] = "VarR4FromCy",
+    [73] = "VarR4FromDate",
+    [75] = "VarR4FromDisp",
+    [76] = "VarR4FromBool",
+    [77] = "SafeArrayGetVartype",
+    [78] = "VarR8FromUI1",
+    [79] = "VarR8FromI2",
+    [80] = "VarR8FromI4",
+    [81] = "VarR8FromR4",
+    [82] = "VarR8FromCy",
+    [83] = "VarR8FromDate",
+    [85] = "VarR8FromDisp",
+    [88] = "VarDateFromUI1",
+    [89] = "VarDateFromI2",
+    [90] = "VarDateFromI4",
+    [91] = "VarDateFromR4",
+    [92] = "VarDateFromR8",
+    [93] = "VarDateFromCy",
+    [95] = "VarDateFromDisp",
+    [96] = "VarDateFromBool",
+    [98] = "VarCyFromUI1",
+    [99] = "VarCyFromI2",
+    [100] = "VarCyFromI4",
+    [102] = "VarCyFromR8",
+    [103] = "VarCyFromDate",
+    [104] = "VarCyFromStr",
+    [105] = "VarCyFromDisp",
+    [106] = "VarCyFromBool",
+    [107] = "VarFormatNumber",
+    [108] = "VarBstrFromUI1",
+    [109] = "VarBstrFromI2",
+    [110] = "VarBstrFromI4",
+    [111] = "VarBstrFromR4",
+    [112] = "VarBstrFromR8",
+    [113] = "VarBstrFromCy",
+    [114] = "VarBstrFromDate",
+    [115] = "VarBstrFromDisp",
+    [116] = "VarBstrFromBool",
+    [119] = "VarBoolFromI2",
+    [120] = "VarBoolFromI4",
+    [121] = "VarBoolFromR4",
+    [122] = "VarBoolFromR8",
+    [123] = "VarBoolFromDate",
+    [124] = "VarBoolFromCy",
+    [125] = "VarBoolFromStr",
+    [126] = "VarBoolFromDisp",
+    [127] = "VarFormatCurrency",
+    [129] = "VarMonthName",
+    [130] = "VarUI1FromI2",
+    [131] = "VarUI1FromI4",
+    [132] = "VarUI1FromR4",
+    [133] = "VarUI1FromR8",
+    [134] = "VarUI1FromCy",
+    [135] = "VarUI1FromDate",
+    [137] = "VarUI1FromDisp",
+    [138] = "VarUI1FromBool",
+    [139] = "VarFormatFromTokens",
+    [140] = "VarTokenizeFormatString",
+    [141] = "VarAdd",
+    [143] = "VarDiv",
+    [144] = "BSTR_UserFree64",
+    [145] = "BSTR_UserMarshal64",
+    [146] = "DispCallFunc",
+    [147] = "VariantChangeTypeEx",
+    [148] = "SafeArrayPtrOfIndex",
+    [149] = "SysStringByteLen",
+    [150] = "SysAllocStringByteLen",
+    [151] = "BSTR_UserSize64",
+    [152] = "VarEqv",
+    [153] = "VarIdiv",
+    [154] = "VarImp",
+    [155] = "VarMod",
+    [156] = "VarMul",
+    [157] = "VarOr",
+    [158] = "VarPow",
+    [159] = "VarSub",
+    [160] = "CreateTypeLib",
+    [161] = "LoadTypeLib",
+    [162] = "LoadRegTypeLib",
+    [163] = "RegisterTypeLib",
+    [164] = "QueryPathOfRegTypeLib",
+    [165] = "LHashValOfNameSys",
+    [166] = "LHashValOfNameSysA",
+    [167] = "VarXor",
+    [168] = "VarAbs",
+    [169] = "VarFix",
+    [170] = "OaBuildVersion",
+    [171] = "ClearCustData",
+    [172] = "VarInt",
+    [173] = "VarNeg",
+    [174] = "VarNot",
+    [175] = "VarRound",
+    [176] = "VarCmp",
+    [177] = "VarDecAdd",
+    [179] = "VarDecMul",
+    [180] = "CreateTypeLib2",
+    [181] = "VarDecSub",
+    [182] = "VarDecAbs",
+    [183] = "LoadTypeLibEx",
+    [184] = "SystemTimeToVariantTime",
+    [185] = "VariantTimeToSystemTime",
+    [186] = "UnRegisterTypeLib",
+    [187] = "VarDecFix",
+    [188] = "VarDecInt",
+    [189] = "VarDecNeg",
+    [190] = "VarDecFromUI1",
+    [191] = "VarDecFromI2",
+    [192] = "VarDecFromI4",
+    [193] = "VarDecFromR4",
+    [194] = "VarDecFromR8",
+    [195] = "VarDecFromDate",
+    [196] = "VarDecFromCy",
+    [197] = "VarDecFromStr",
+    [198] = "VarDecFromDisp",
+    [199] = "VarDecFromBool",
+    [200] = "GetErrorInfo",
+    [201] = "SetErrorInfo",
+    [202] = "CreateErrorInfo",
+    [203] = "VarDecRound",
+    [204] = "VarDecCmp",
+    [205] = "VarI2FromI1",
+    [206] = "VarI2FromUI2",
+    [207] = "VarI2FromUI4",
+    [208] = "VarI2FromDec",
+    [209] = "VarI4FromI1",
+    [210] = "VarI4FromUI2",
+    [211] = "VarI4FromUI4",
+    [212] = "VarI4FromDec",
+    [213] = "VarR4FromI1",
+    [214] = "VarR4FromUI2",
+    [215] = "VarR4FromUI4",
+    [216] = "VarR4FromDec",
+    [217] = "VarR8FromI1",
+    [218] = "VarR8FromUI2",
+    [219] = "VarR8FromUI4",
+    [220] = "VarR8FromDec",
+    [221] = "VarDateFromI1",
+    [222] = "VarDateFromUI2",
+    [223] = "VarDateFromUI4",
+    [224] = "VarDateFromDec",
+    [225] = "VarCyFromI1",
+    [226] = "VarCyFromUI2",
+    [227] = "VarCyFromUI4",
+    [228] = "VarCyFromDec",
+    [229] = "VarBstrFromI1",
+    [230] = "VarBstrFromUI2",
+    [232] = "VarBstrFromDec",
+    [233] = "VarBoolFromI1",
+    [234] = "VarBoolFromUI2",
+    [235] = "VarBoolFromUI4",
+    [236] = "VarBoolFromDec",
+    [238] = "VarUI1FromUI2",
+    [239] = "VarUI1FromUI4",
+    [240] = "VarUI1FromDec",
+    [241] = "VarDecFromI1",
+    [242] = "VarDecFromUI2",
+    [243] = "VarDecFromUI4",
+    [244] = "VarI1FromUI1",
+    [245] = "VarI1FromI2",
+    [246] = "VarI1FromI4",
+    [247] = "VarI1FromR4",
+    [248] = "VarI1FromR8",
+    [249] = "VarI1FromDate",
+    [250] = "VarI1FromCy",
+    [251] = "VarI1FromStr",
+    [252] = "VarI1FromDisp",
+    [253] = "VarI1FromBool",
+    [254] = "VarI1FromUI2",
+    [255] = "VarI1FromUI4",
+    [256] = "VarI1FromDec",
+    [258] = "VarUI2FromI2",
+    [259] = "VarUI2FromI4",
+    [260] = "VarUI2FromR4",
+    [261] = "VarUI2FromR8",
+    [262] = "VarUI2FromDate",
+    [263] = "VarUI2FromCy",
+    [265] = "VarUI2FromDisp",
+    [266] = "VarUI2FromBool",
+    [267] = "VarUI2FromI1",
+    [269] = "VarUI2FromDec",
+    [270] = "VarUI4FromUI1",
+    [271] = "VarUI4FromI2",
+    [272] = "VarUI4FromI4",
+    [273] = "VarUI4FromR4",
+    [274] = "VarUI4FromR8",
+    [275] = "VarUI4FromDate",
+    [276] = "VarUI4FromCy",
+    [278] = "VarUI4FromDisp",
+    [280] = "VarUI4FromI1",
+    [281] = "VarUI4FromUI2",
+    [282] = "VarUI4FromDec",
+    [283] = "BSTR_UserSize",
+    [284] = "BSTR_UserMarshal",
+    [285] = "BSTR_UserUnmarshal",
+    [286] = "BSTR_UserFree",
+    [287] = "VARIANT_UserSize",
+    [288] = "VARIANT_UserMarshal",
+    [289] = "VARIANT_UserUnmarshal",
+    [290] = "VARIANT_UserFree",
+    [291] = "LPSAFEARRAY_UserSize",
+    [292] = "LPSAFEARRAY_UserMarshal",
+    [293] = "LPSAFEARRAY_UserUnmarshal",
+    [294] = "LPSAFEARRAY_UserFree",
+    [295] = "LPSAFEARRAY_Size",
+    [296] = "LPSAFEARRAY_Marshal",
+    [297] = "LPSAFEARRAY_Unmarshal",
+    [298] = "VarDecCmpR8",
+    [299] = "VarCyAdd",
+    [300] = "BSTR_UserUnmarshal64",
+    [301] = "DllCanUnloadNow",
+    [302] = "DllGetClassObject",
+    [303] = "VarCyMul",
+    [304] = "VarCyMulI4",
+    [305] = "VarCySub",
+    [306] = "VarCyAbs",
+    [307] = "VarCyFix",
+    [308] = "VarCyInt",
+    [309] = "VarCyNeg",
+    [310] = "VarCyRound",
+    [311] = "VarCyCmp",
+    [312] = "VarCyCmpR8",
+    [313] = "VarBstrCat",
+    [314] = "VarBstrCmp",
+    [315] = "VarR8Pow",
+    [316] = "VarR4CmpR8",
+    [317] = "VarR8Round",
+    [318] = "VarCat",
+    [319] = "VarDateFromUdateEx",
+    [320] = "DllRegisterServer",
+    [321] = "DllUnregisterServer",
+    [322] = "GetRecordInfoFromGuids",
+    [323] = "GetRecordInfoFromTypeInfo",
+    [324] = "LPSAFEARRAY_UserFree64",
+    [325] = "SetVarConversionLocaleSetting",
+    [326] = "GetVarConversionLocaleSetting",
+    [327] = "SetOaNoCache",
+    [328] = "LPSAFEARRAY_UserMarshal64",
+    [329] = "VarCyMulI8",
+    [330] = "VarDateFromUdate",
+    [332] = "GetAltMonthNames",
+    [333] = "VarI8FromUI1",
+    [334] = "VarI8FromI2",
+    [335] = "VarI8FromR4",
+    [336] = "VarI8FromR8",
+    [337] = "VarI8FromCy",
+    [338] = "VarI8FromDate",
+    [340] = "VarI8FromDisp",
+    [341] = "VarI8FromBool",
+    [342] = "VarI8FromI1",
+    [343] = "VarI8FromUI2",
+    [344] = "VarI8FromUI4",
+    [345] = "VarI8FromDec",
+    [346] = "VarI2FromI8",
+    [347] = "VarI2FromUI8",
+    [348] = "VarI4FromI8",
+    [349] = "VarI4FromUI8",
+    [350] = "LPSAFEARRAY_UserSize64",
+    [351] = "LPSAFEARRAY_UserUnmarshal64",
+    [352] = "OACreateTypeLib2",
+    [353] = "SafeArrayAddRef",
+    [354] = "SafeArrayReleaseData",
+    [355] = "SafeArrayReleaseDescriptor",
+    [356] = "SysAddRefString",
+    [357] = "SysReleaseString",
+    [358] = "VARIANT_UserFree64",
+    [359] = "VARIANT_UserMarshal64",
+    [360] = "VarR4FromI8",
+    [361] = "VarR4FromUI8",
+    [362] = "VarR8FromI8",
+    [363] = "VarR8FromUI8",
+    [364] = "VarDateFromI8",
+    [365] = "VarDateFromUI8",
+    [366] = "VarCyFromI8",
+    [367] = "VarCyFromUI8",
+    [368] = "VarBstrFromI8",
+    [370] = "VarBoolFromI8",
+    [372] = "VarUI1FromI8",
+    [373] = "VarUI1FromUI8",
+    [374] = "VarDecFromI8",
+    [375] = "VarDecFromUI8",
+    [376] = "VarI1FromI8",
+    [378] = "VarUI2FromI8",
+    [379] = "VarUI2FromUI8",
+    [411] = "SafeArrayCreateVector",
+    [412] = "SafeArrayCopyData",
+    [413] = "VectorFromBstr",
+    [414] = "BstrFromVector",
+    [415] = "OleIconToCursor",
+    [416] = "OleCreatePropertyFrameIndirect",
+    [417] = "OleCreatePropertyFrame",
+    [418] = "OleLoadPicture",
+    [419] = "OleCreatePictureIndirect",
+    [420] = "OleCreateFontIndirect",
+    [421] = "OleTranslateColor",
+    [422] = "OleLoadPictureFile",
+    [424] = "OleLoadPicturePath",
+    [425] = "VarUI4FromI8",
+    [426] = "VarUI4FromUI8",
+    [427] = "VarI8FromUI8",
+    [428] = "VarUI8FromI8",
+    [429] = "VarUI8FromUI1",
+    [430] = "VarUI8FromI2",
+    [431] = "VarUI8FromR4",
+    [432] = "VarUI8FromR8",
+    [433] = "VarUI8FromCy",
+    [434] = "VarUI8FromDate",
+    [436] = "VarUI8FromDisp",
+    [439] = "VarUI8FromUI2",
+    [440] = "VarUI8FromUI4",
+    [441] = "VarUI8FromDec",
+    [442] = "RegisterTypeLibForUser",
+    [443] = "UnRegisterTypeLibForUser",
+    [444] = "OaEnablePerUserTLibRegistration",
+    [445] = "HWND_UserFree",
+    [446] = "HWND_UserMarshal",
+    [447] = "HWND_UserSize",
+    [448] = "HWND_UserUnmarshal",
+    [449] = "HWND_UserFree64",
+    [450] = "HWND_UserMarshal64",
+    [500] = "OACleanup",
+};
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ordinal = valeur ordinale à considérer.                      *
+*                                                                             *
+*  Description : Fournit le nom du symbole associé à un ordinal donné.        *
+*                                                                             *
+*  Retour      : Désignation du symbole trouvé ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *find_oleaut32_name_for_ordinal(uint16_t ordinal)
+{
+    const char *result;                     /* Désignation à renvoyer      */
+
+    if (ordinal >= 501)
+        result = NULL;
+
+    else
+        result = _oleaut32_ordinals[ordinal];
+
+    return result;
+
+}
diff --git a/plugins/winordinals/cache_oleaut32.h b/plugins/winordinals/cache_oleaut32.h
new file mode 100644
index 0000000..ec9e344
--- /dev/null
+++ b/plugins/winordinals/cache_oleaut32.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_oleaut32.h - prototypes pour la fourniture des ordinaux du fichier oleaut32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_CACHE_OLEAUT32_H
+#define _PLUGINS_WINORDINALS_CACHE_OLEAUT32_H
+
+
+#include <stdint.h>
+
+
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char *find_oleaut32_name_for_ordinal(uint16_t);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_CACHE_OLEAUT32_H */
diff --git a/plugins/winordinals/cache_ws2_32.c b/plugins/winordinals/cache_ws2_32.c
new file mode 100644
index 0000000..fbf76ac
--- /dev/null
+++ b/plugins/winordinals/cache_ws2_32.c
@@ -0,0 +1,260 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_ws2_32.c - fourniture des ordinaux du fichier ws2_32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cache_ws2_32.h"
+
+
+#include <stddef.h>
+
+
+
+/**
+ * Empreintes du fichier ws2_32.dll :
+ *
+ *   - MD5 : f1fafc04216614ec5c7b8c6a82394dfd
+ *   - SHA1 : 5b6966d9af7bcf687aab982c26efe1c2adfaff18
+ *   - SHA256 : 7e412388c871f5f1d1651da11689eb82a7e4c5785409ec2753cfc4be484d910e
+ */
+
+
+/* Liste des ordinaux référencés */
+static const char *_ws2_32_ordinals[501] = {
+    [1] = "accept",
+    [2] = "bind",
+    [3] = "closesocket",
+    [4] = "connect",
+    [5] = "getpeername",
+    [6] = "getsockname",
+    [7] = "getsockopt",
+    [8] = "htonl",
+    [9] = "htons",
+    [10] = "ioctlsocket",
+    [11] = "inet_addr",
+    [12] = "inet_ntoa",
+    [15] = "ntohs",
+    [16] = "recv",
+    [17] = "recvfrom",
+    [18] = "select",
+    [19] = "send",
+    [20] = "sendto",
+    [21] = "setsockopt",
+    [22] = "shutdown",
+    [23] = "socket",
+    [25] = "FreeAddrInfoEx",
+    [26] = "FreeAddrInfoExW",
+    [27] = "FreeAddrInfoW",
+    [28] = "GetAddrInfoExA",
+    [29] = "GetAddrInfoExCancel",
+    [30] = "GetAddrInfoExOverlappedResult",
+    [31] = "GetAddrInfoExW",
+    [32] = "GetAddrInfoW",
+    [33] = "GetHostNameW",
+    [34] = "GetNameInfoW",
+    [35] = "InetNtopW",
+    [36] = "InetPtonW",
+    [37] = "SetAddrInfoExA",
+    [38] = "SetAddrInfoExW",
+    [39] = "WPUCompleteOverlappedRequest",
+    [40] = "WPUGetProviderPathEx",
+    [41] = "WSAAccept",
+    [42] = "WSAAddressToStringA",
+    [43] = "WSAAddressToStringW",
+    [44] = "WSAAdvertiseProvider",
+    [45] = "WSACloseEvent",
+    [46] = "WSAConnect",
+    [47] = "WSAConnectByList",
+    [48] = "WSAConnectByNameA",
+    [49] = "WSAConnectByNameW",
+    [50] = "WSACreateEvent",
+    [51] = "gethostbyaddr",
+    [52] = "gethostbyname",
+    [53] = "getprotobyname",
+    [54] = "getprotobynumber",
+    [55] = "getservbyname",
+    [56] = "getservbyport",
+    [57] = "gethostname",
+    [58] = "WSADuplicateSocketA",
+    [59] = "WSADuplicateSocketW",
+    [60] = "WSAEnumNameSpaceProvidersA",
+    [61] = "WSAEnumNameSpaceProvidersExA",
+    [62] = "WSAEnumNameSpaceProvidersExW",
+    [63] = "WSAEnumNameSpaceProvidersW",
+    [64] = "WSAEnumNetworkEvents",
+    [65] = "WSAEnumProtocolsA",
+    [66] = "WSAEnumProtocolsW",
+    [67] = "WSAEventSelect",
+    [68] = "WSAGetOverlappedResult",
+    [69] = "WSAGetQOSByName",
+    [70] = "WSAGetServiceClassInfoA",
+    [71] = "WSAGetServiceClassInfoW",
+    [72] = "WSAGetServiceClassNameByClassIdA",
+    [73] = "WSAGetServiceClassNameByClassIdW",
+    [74] = "WSAHtonl",
+    [75] = "WSAHtons",
+    [76] = "WSAInstallServiceClassA",
+    [77] = "WSAInstallServiceClassW",
+    [78] = "WSAIoctl",
+    [79] = "WSAJoinLeaf",
+    [80] = "WSALookupServiceBeginA",
+    [81] = "WSALookupServiceBeginW",
+    [82] = "WSALookupServiceEnd",
+    [83] = "WSALookupServiceNextA",
+    [84] = "WSALookupServiceNextW",
+    [85] = "WSANSPIoctl",
+    [86] = "WSANtohl",
+    [87] = "WSANtohs",
+    [88] = "WSAPoll",
+    [89] = "WSAProviderCompleteAsyncCall",
+    [90] = "WSAProviderConfigChange",
+    [91] = "WSARecv",
+    [92] = "WSARecvDisconnect",
+    [93] = "WSARecvFrom",
+    [94] = "WSARemoveServiceClass",
+    [95] = "WSAResetEvent",
+    [96] = "WSASend",
+    [97] = "WSASendDisconnect",
+    [98] = "WSASendMsg",
+    [99] = "WSASendTo",
+    [100] = "WSASetEvent",
+    [101] = "WSAAsyncSelect",
+    [102] = "WSAAsyncGetHostByAddr",
+    [103] = "WSAAsyncGetHostByName",
+    [104] = "WSAAsyncGetProtoByNumber",
+    [105] = "WSAAsyncGetProtoByName",
+    [106] = "WSAAsyncGetServByPort",
+    [107] = "WSAAsyncGetServByName",
+    [108] = "WSACancelAsyncRequest",
+    [109] = "WSASetBlockingHook",
+    [110] = "WSAUnhookBlockingHook",
+    [111] = "WSAGetLastError",
+    [112] = "WSASetLastError",
+    [113] = "WSACancelBlockingCall",
+    [114] = "WSAIsBlocking",
+    [115] = "WSAStartup",
+    [116] = "WSACleanup",
+    [117] = "WSASetServiceA",
+    [118] = "WSASetServiceW",
+    [119] = "WSASocketA",
+    [120] = "WSASocketW",
+    [121] = "WSAStringToAddressA",
+    [122] = "WSAStringToAddressW",
+    [123] = "WSAUnadvertiseProvider",
+    [124] = "WSAWaitForMultipleEvents",
+    [125] = "WSCDeinstallProvider",
+    [126] = "WSCDeinstallProvider32",
+    [127] = "WSCDeinstallProviderEx",
+    [128] = "WSCEnableNSProvider",
+    [129] = "WSCEnableNSProvider32",
+    [130] = "WSCEnumNameSpaceProviders32",
+    [131] = "WSCEnumNameSpaceProvidersEx32",
+    [132] = "WSCEnumProtocols",
+    [133] = "WSCEnumProtocols32",
+    [134] = "WSCEnumProtocolsEx",
+    [135] = "WSCGetApplicationCategory",
+    [136] = "WSCGetApplicationCategoryEx",
+    [137] = "WSCGetProviderInfo",
+    [138] = "WSCGetProviderInfo32",
+    [139] = "WSCGetProviderPath",
+    [140] = "WSCGetProviderPath32",
+    [141] = "WSCInstallNameSpace",
+    [142] = "WSCInstallNameSpace32",
+    [143] = "WSCInstallNameSpaceEx",
+    [144] = "WSCInstallNameSpaceEx2",
+    [145] = "WSCInstallNameSpaceEx32",
+    [146] = "WSCInstallProvider",
+    [147] = "WSCInstallProvider64_32",
+    [148] = "WSCInstallProviderAndChains64_32",
+    [149] = "WSCInstallProviderEx",
+    [150] = "WSCSetApplicationCategory",
+    [151] = "__WSAFDIsSet",
+    [152] = "WSCSetApplicationCategoryEx",
+    [153] = "WSCSetProviderInfo",
+    [154] = "WSCSetProviderInfo32",
+    [155] = "WSCUnInstallNameSpace",
+    [156] = "WSCUnInstallNameSpace32",
+    [157] = "WSCUnInstallNameSpaceEx2",
+    [158] = "WSCUpdateProvider",
+    [159] = "WSCUpdateProvider32",
+    [160] = "WSCUpdateProviderEx",
+    [161] = "WSCWriteNameSpaceOrder",
+    [162] = "WSCWriteNameSpaceOrder32",
+    [163] = "WSCWriteProviderOrder",
+    [164] = "WSCWriteProviderOrder32",
+    [165] = "WSCWriteProviderOrderEx",
+    [166] = "WahCloseApcHelper",
+    [167] = "WahCloseHandleHelper",
+    [168] = "WahCloseNotificationHandleHelper",
+    [169] = "WahCloseSocketHandle",
+    [170] = "WahCloseThread",
+    [171] = "WahCompleteRequest",
+    [172] = "WahCreateHandleContextTable",
+    [173] = "WahCreateNotificationHandle",
+    [174] = "WahCreateSocketHandle",
+    [175] = "WahDestroyHandleContextTable",
+    [176] = "WahDisableNonIFSHandleSupport",
+    [177] = "WahEnableNonIFSHandleSupport",
+    [178] = "WahEnumerateHandleContexts",
+    [179] = "WahInsertHandleContext",
+    [180] = "WahNotifyAllProcesses",
+    [181] = "WahOpenApcHelper",
+    [182] = "WahOpenCurrentThread",
+    [183] = "WahOpenHandleHelper",
+    [184] = "WahOpenNotificationHandleHelper",
+    [185] = "WahQueueUserApc",
+    [186] = "WahReferenceContextByHandle",
+    [187] = "WahRemoveHandleContext",
+    [188] = "WahWaitForNotification",
+    [190] = "freeaddrinfo",
+    [191] = "getaddrinfo",
+    [192] = "getnameinfo",
+    [193] = "inet_ntop",
+    [500] = "WEP",
+};
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ordinal = valeur ordinale à considérer.                      *
+*                                                                             *
+*  Description : Fournit le nom du symbole associé à un ordinal donné.        *
+*                                                                             *
+*  Retour      : Désignation du symbole trouvé ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *find_ws2_32_name_for_ordinal(uint16_t ordinal)
+{
+    const char *result;                     /* Désignation à renvoyer      */
+
+    if (ordinal >= 501)
+        result = NULL;
+
+    else
+        result = _ws2_32_ordinals[ordinal];
+
+    return result;
+
+}
diff --git a/plugins/winordinals/cache_ws2_32.h b/plugins/winordinals/cache_ws2_32.h
new file mode 100644
index 0000000..cfc546d
--- /dev/null
+++ b/plugins/winordinals/cache_ws2_32.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_ws2_32.h - prototypes pour la fourniture des ordinaux du fichier ws2_32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_CACHE_WS2_32_H
+#define _PLUGINS_WINORDINALS_CACHE_WS2_32_H
+
+
+#include <stdint.h>
+
+
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char *find_ws2_32_name_for_ordinal(uint16_t);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_CACHE_WS2_32_H */
diff --git a/plugins/winordinals/cache_wsock32.c b/plugins/winordinals/cache_wsock32.c
new file mode 100644
index 0000000..d3b98cf
--- /dev/null
+++ b/plugins/winordinals/cache_wsock32.c
@@ -0,0 +1,137 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_wsock32.c - fourniture des ordinaux du fichier wsock32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cache_wsock32.h"
+
+
+#include <stddef.h>
+
+
+
+/**
+ * Empreintes du fichier wsock32.dll :
+ *
+ *   - MD5 : 2afbb671a865f43c0476d685dc77b4df
+ *   - SHA1 : 233125ad8fd18a65d5939b80160ce3e5c19c0184
+ *   - SHA256 : 0c310f70350ba9801f0421c2da2595beaa3fef55d43d6928d53a674dfcd6e9fb
+ */
+
+
+/* Liste des ordinaux référencés */
+static const char *_wsock32_ordinals[1143] = {
+    [1] = "accept",
+    [2] = "bind",
+    [3] = "closesocket",
+    [4] = "connect",
+    [5] = "getpeername",
+    [6] = "getsockname",
+    [7] = "getsockopt",
+    [8] = "htonl",
+    [9] = "htons",
+    [10] = "inet_addr",
+    [11] = "inet_ntoa",
+    [12] = "ioctlsocket",
+    [13] = "listen",
+    [14] = "ntohl",
+    [15] = "ntohs",
+    [16] = "recv",
+    [17] = "recvfrom",
+    [18] = "select",
+    [19] = "send",
+    [20] = "sendto",
+    [21] = "setsockopt",
+    [22] = "shutdown",
+    [23] = "socket",
+    [51] = "gethostbyaddr",
+    [52] = "gethostbyname",
+    [53] = "getprotobyname",
+    [54] = "getprotobynumber",
+    [55] = "getservbyname",
+    [56] = "getservbyport",
+    [101] = "WSAAsyncSelect",
+    [102] = "WSAAsyncGetHostByAddr",
+    [103] = "WSAAsyncGetHostByName",
+    [104] = "WSAAsyncGetProtoByNumber",
+    [105] = "WSAAsyncGetProtoByName",
+    [106] = "WSAAsyncGetServByPort",
+    [107] = "WSAAsyncGetServByName",
+    [108] = "WSACancelAsyncRequest",
+    [109] = "WSASetBlockingHook",
+    [110] = "WSAUnhookBlockingHook",
+    [111] = "WSAGetLastError",
+    [112] = "WSASetLastError",
+    [113] = "WSACancelBlockingCall",
+    [114] = "WSAIsBlocking",
+    [115] = "WSAStartup",
+    [1100] = "inet_network",
+    [1101] = "getnetbyname",
+    [1102] = "rcmd",
+    [1103] = "rexec",
+    [1104] = "rresvport",
+    [1105] = "sethostname",
+    [1106] = "dn_expand",
+    [1107] = "WSARecvEx",
+    [1108] = "s_perror",
+    [1109] = "GetAddressByNameA",
+    [1110] = "GetAddressByNameW",
+    [1111] = "EnumProtocolsA",
+    [1112] = "EnumProtocolsW",
+    [1113] = "GetTypeByNameA",
+    [1114] = "GetTypeByNameW",
+    [1115] = "GetNameByTypeA",
+    [1116] = "GetNameByTypeW",
+    [1117] = "SetServiceA",
+    [1118] = "SetServiceW",
+    [1119] = "GetServiceA",
+    [1140] = "TransmitFile",
+    [1141] = "AcceptEx",
+    [1142] = "GetAcceptExSockaddrs",
+};
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ordinal = valeur ordinale à considérer.                      *
+*                                                                             *
+*  Description : Fournit le nom du symbole associé à un ordinal donné.        *
+*                                                                             *
+*  Retour      : Désignation du symbole trouvé ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *find_wsock32_name_for_ordinal(uint16_t ordinal)
+{
+    const char *result;                     /* Désignation à renvoyer      */
+
+    if (ordinal >= 1143)
+        result = NULL;
+
+    else
+        result = _wsock32_ordinals[ordinal];
+
+    return result;
+
+}
diff --git a/plugins/winordinals/cache_wsock32.h b/plugins/winordinals/cache_wsock32.h
new file mode 100644
index 0000000..0246360
--- /dev/null
+++ b/plugins/winordinals/cache_wsock32.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_wsock32.h - prototypes pour la fourniture des ordinaux du fichier wsock32.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_CACHE_WSOCK32_H
+#define _PLUGINS_WINORDINALS_CACHE_WSOCK32_H
+
+
+#include <stdint.h>
+
+
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char *find_wsock32_name_for_ordinal(uint16_t);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_CACHE_WSOCK32_H */
diff --git a/plugins/winordinals/core.c b/plugins/winordinals/core.c
new file mode 100644
index 0000000..a16c400
--- /dev/null
+++ b/plugins/winordinals/core.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - connaissance de valeurs ordinales pour certains fichiers DLL
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <assert.h>
+
+
+#include <plugins/self.h>
+
+
+#include "assign.h"
+#ifdef HAVE_PYTHON3_BINDINGS
+#   include "python/module.h"
+#endif
+
+
+#ifdef HAVE_PYTHON3_BINDINGS
+#   define PG_REQ RL("PyChrysalide")
+#else
+#   define PG_REQ NO_REQ
+#endif
+
+
+DEFINE_CHRYSALIDE_PLUGIN("WinOrdinals", "Ordinals database for some DLL files",
+                         PACKAGE_VERSION, CHRYSALIDE_WEBSITE(""),
+                         PG_REQ, AL(PGA_PLUGIN_INIT, PGA_FORMAT_ANALYSIS_ENDED));
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                                                                             *
+*  Description : Prend acte du chargement du greffon.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+#ifdef HAVE_PYTHON3_BINDINGS
+
+    if (result)
+        result = add_winordinals_module_to_python_module();
+
+    if (result)
+        result = populate_winordinals_module();
+
+#endif
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Procède à une opération liée à l'analyse d'un format.        *
+*                                                                             *
+*  Retour      : Bilan de l'exécution du traitement.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    assert(action == PGA_FORMAT_ANALYSIS_ENDED);
+
+    if (G_IS_PE_FORMAT(format))
+        assign_name_imported_ordinals(G_PE_FORMAT(format), status);
+
+    return true;
+
+}
diff --git a/plugins/winordinals/core.h b/plugins/winordinals/core.h
new file mode 100644
index 0000000..cb8e0e3
--- /dev/null
+++ b/plugins/winordinals/core.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la connaissance de valeurs ordinales pour certains fichiers DLL
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_CORE_H
+#define _PLUGINS_WINORDINALS_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+/* Procède à une opération liée à l'analyse d'un format. */
+G_MODULE_EXPORT bool chrysalide_plugin_handle_binary_format_analysis(const GPluginModule *, PluginAction, GKnownFormat *, wgroup_id_t, GtkStatusStack *);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_CORE_H */
diff --git a/plugins/winordinals/ordinals.c b/plugins/winordinals/ordinals.c
new file mode 100644
index 0000000..fd2d27f
--- /dev/null
+++ b/plugins/winordinals/ordinals.c
@@ -0,0 +1,109 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ordinals.c - accès à l'ensemble des ordinaux enregistrés
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "ordinals.h"
+
+
+#include <ctype.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "cache_oleaut32.h"
+#include "cache_ws2_32.h"
+#include "cache_wsock32.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Indique la liste de bibliothèques enregistrées avec ordinaux.*
+*                                                                             *
+*  Retour      : Liste de fichiers DLL pris en charge.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char **list_register_dlls_for_ordinals(void)
+{
+    const char **result;                    /* Liste à retourner           */
+
+    result = malloc(3 * sizeof(char *));
+
+    result[0] = strdup("oleaut32.dll");
+    result[1] = strdup("ws2_32.dll");
+    result[2] = strdup("wsock32.dll");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Indique la liste de bibliothèques enregistrées avec ordinaux.*
+*                                                                             *
+*  Retour      : Liste de fichiers DLL pris en charge.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *get_symbol_by_ordinal(const char *dll, uint16_t ordinal)
+{
+    const char *result;                     /* Désignation à retourner     */
+    size_t len;                             /* Taille de la chaîne         */
+    char *lower_dll;                        /* Version en minuscules       */
+    size_t i;                               /* Boucle de parcours          */
+
+    len = strlen(dll);
+
+    lower_dll = malloc(len + 1);
+
+    for (i = 0; i < len; i++)
+        lower_dll[i] = tolower(dll[i]);
+
+    lower_dll[len] = '\0';
+
+    if (strcmp(lower_dll, "oleaut32.dll") == 0)
+        result = find_oleaut32_name_for_ordinal(ordinal);
+
+    else if (strcmp(lower_dll, "ws2_32.dll") == 0)
+        result = find_ws2_32_name_for_ordinal(ordinal);
+
+    else if (strcmp(lower_dll, "wsock32.dll") == 0)
+        result = find_wsock32_name_for_ordinal(ordinal);
+
+    else
+        result = NULL;
+
+    free(lower_dll);
+
+    return result;
+
+}
diff --git a/plugins/winordinals/ordinals.h b/plugins/winordinals/ordinals.h
new file mode 100644
index 0000000..e7b044c
--- /dev/null
+++ b/plugins/winordinals/ordinals.h
@@ -0,0 +1,40 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ordinals.h - prototypes pour l'accès à l'ensemble des ordinaux enregistrés
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_ORDINALS_H
+#define _PLUGINS_WINORDINALS_ORDINALS_H
+
+
+#include <stdint.h>
+
+
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char **list_register_dlls_for_ordinals(void);
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char *get_symbol_by_ordinal(const char *, uint16_t);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_ORDINALS_H */
diff --git a/plugins/winordinals/python/Makefile.am b/plugins/winordinals/python/Makefile.am
new file mode 100644
index 0000000..a5f17a4
--- /dev/null
+++ b/plugins/winordinals/python/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libwinordinalspython.la
+
+libwinordinalspython_la_SOURCES =			\
+	module.h module.c
+
+libwinordinalspython_la_LDFLAGS = 
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libwinordinalspython_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/winordinals/python/module.c b/plugins/winordinals/python/module.c
new file mode 100644
index 0000000..03ad5ef
--- /dev/null
+++ b/plugins/winordinals/python/module.c
@@ -0,0 +1,112 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire winordinals en tant que module
+ *
+ * Copyright (C) 2021 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 "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Ajoute le module 'plugins.winordinals' au module Python.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_winordinals_module_to_python_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *super;                        /* Module à compléter          */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_PLUGINS_WINORDINALS_DOC                        \
+    "winordinals is a module providing the value of known ordinals" \
+    " for some DLL files."
+
+    static PyModuleDef py_chrysalide_winordinals_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.plugins.winordinals",
+        .m_doc = PYCHRYSALIDE_PLUGINS_WINORDINALS_DOC,
+
+        .m_size = -1,
+
+    };
+
+    result = false;
+
+    super = get_access_to_python_module("pychrysalide.plugins");
+
+    module = build_python_module(super, &py_chrysalide_winordinals_module);
+
+    result = (module != NULL);
+
+    assert(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Intègre les objets du module 'plugins.winordinals'.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_winordinals_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Module à recompléter        */
+
+    result = true;
+
+    module = get_access_to_python_module("pychrysalide.plugins.winordinals");
+
+    //if (result) result = register_python_winordinals_node(module);
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/winordinals/python/module.h b/plugins/winordinals/python/module.h
new file mode 100644
index 0000000..d1c1d5c
--- /dev/null
+++ b/plugins/winordinals/python/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire winordinals en tant que module
+ *
+ * Copyright (C) 2021 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_WINORDINALS_PYTHON_MODULE_H
+#define _PLUGINS_WINORDINALS_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.winordinals' au module Python. */
+bool add_winordinals_module_to_python_module(void);
+
+/* Intègre les objets du module 'plugins.winordinals'. */
+bool populate_winordinals_module(void);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_PYTHON_MODULE_H */
diff --git a/tools/ordinals/cache-pe-exports.py b/tools/ordinals/cache-pe-exports.py
new file mode 100644
index 0000000..b2ab97e
--- /dev/null
+++ b/tools/ordinals/cache-pe-exports.py
@@ -0,0 +1,218 @@
+
+import argparse
+import hashlib
+import os
+
+import pychrysalide
+from pychrysalide.analysis.contents import FileContent
+from pychrysalide.format import BinSymbol
+from pychrysalide.format.pe import PeFormat
+
+
+
+def write_header(directory, name):
+    """Ecrit le fichier d'entête pour la transcription d'ordinaux."""
+
+    content = '''
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_%s.h - prototypes pour la fourniture des ordinaux du fichier %s.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_WINORDINALS_CACHE_%s_H
+#define _PLUGINS_WINORDINALS_CACHE_%s_H
+
+
+#include <stdint.h>
+
+
+
+/* Indique la liste de bibliothèques enregistrées avec ordinaux. */
+const char *find_%s_name_for_ordinal(uint16_t);
+
+
+
+#endif  /* _PLUGINS_WINORDINALS_CACHE_%s_H */
+''' \
+    % (name, name, name.upper(), name.upper(), name, name.upper())
+
+    with open(os.path.join(directory, 'cache_%s.h' % name), 'w') as fd:
+        fd.write(content)
+
+
+def write_code(directory, name, hashes, exported):
+    """Ecrit le fichier d'entête pour la transcription d'ordinaux."""
+
+    content_prologue = '''
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache_%s.c - fourniture des ordinaux du fichier %s.dll
+ *
+ * Copyright (C) 2021 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cache_%s.h"
+
+
+#include <stddef.h>
+
+
+
+/**
+ * Empreintes du fichier %s.dll :
+ *
+ *   - MD5 : %s
+ *   - SHA1 : %s
+ *   - SHA256 : %s
+ */
+
+
+/* Liste des ordinaux référencés */
+''' \
+    % (name, name, name, name, hashes['md5'], hashes['sha1'], hashes['sha256'])
+
+
+    content_epilogue = '''
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ordinal = valeur ordinale à considérer.                      *
+*                                                                             *
+*  Description : Fournit le nom du symbole associé à un ordinal donné.        *
+*                                                                             *
+*  Retour      : Désignation du symbole trouvé ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *find_%s_name_for_ordinal(uint16_t ordinal)
+{
+    const char *result;                     /* Désignation à renvoyer      */
+
+    if (ordinal >= %u)
+        result = NULL;
+
+    else
+        result = _%s_ordinals[ordinal];
+
+    return result;
+
+}
+''' % (name, exported[-1][0] + 1, name)
+
+    with open(os.path.join(directory, 'cache_%s.c' % name), 'w') as fd:
+
+        fd.write(content_prologue)
+
+        fd.write('static const char *_%s_ordinals[%u] = {\n' % (name, exported[-1][0] + 1))
+
+        for e in exported:
+
+            fd.write('    [%u] = "%s",\n' % (e[0], e[1]))
+
+        fd.write('};\n')
+
+        fd.write(content_epilogue)
+
+
+def get_internal_name(filename):
+    """Fournit le nom de la bibliothèque pour les désignations internes."""
+
+    name = os.path.basename(filename)
+
+    idx = name.find('.')
+
+    name = name[:idx].lower()
+
+    return name
+
+
+def compute_hashs(filename):
+    """Calcule les empreintes du fichier analysé."""
+
+    with open(filename, 'rb') as fd:
+        data = fd.read()
+
+    hashes = {
+        'md5': hashlib.md5(data).hexdigest(),
+        'sha1': hashlib.sha1(data).hexdigest(),
+        'sha256': hashlib.sha256(data).hexdigest(),
+    }
+
+    return hashes
+
+
+def retrieve_ordinals(filename):
+    """Etablit une liste ordonnée d'ordinaux."""
+
+    cnt = FileContent(filename)
+
+    fmt = PeFormat(cnt)
+    fmt.analyze()
+
+    exported = []
+
+    for s in fmt.symbols:
+
+        if s.status == BinSymbol.SymbolStatus.EXPORTED:
+
+            exported.append([ s.ordinal, s.name ])
+
+    exported = sorted(exported, key=lambda sym: sym[0])
+
+    return exported
+
+
+if __name__ == '__main__':
+    """Point d'entrée du script."""
+
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument('dll', help='path to the library to process')
+    parser.add_argument('dir', help='output directory for the final C files')
+
+    args = parser.parse_args()
+
+    name = get_internal_name(args.dll)
+
+    hashes = compute_hashs(args.dll)
+
+    exported = retrieve_ordinals(args.dll)
+
+    write_header(args.dir, name)
+
+    write_code(args.dir, name, hashes, exported)
-- 
cgit v0.11.2-87-g4458