Comment créer vos propres Bibliothèques d'Importation pour MASM32

(How toCreate your own MASM Import Libraries)

par Iczelion
Ce court essai concerne les mécanismes de création des bibliothèques d'importation pour une utilisation avec MASM. Je présumerai que vous sachiez déjà certaines choses à propos des bibliothèques d'importation, c'est-à-dire. Vous que vous sachiez ce qu'est une bibliothèque d'importation, et cetera. Je me concentrerai sur la technique utilisée habituellement pour produire votre propre bibliothèques d'importation Masm.

Format d'une Bibliothèque d'Importation sous MASM

MASM et Visual C++ peuvent se servir des mêmes bibliothèques d'importation, ce qui est très pratique. Les bibliothèques d'importation de Microsoft utilisent une variante du format de fichier COFF qui diffère du format OMF employé par TASM. C'est cela que TASM ne peut pas employer les importations libs de MASM et vice versa. Je n'entrerai pas dans les détails des formats des bibliothèques d'importation de Microsoft. C'est suffisant de savoir que chaque importe lib Microsoft contient les informations à propos des fonctions qui sont présentes dans certaines DLLs. Ces informations incluent les noms des fonctions et la taille complète des paramètres a passer à ces fonctions. Si vous examinez kernel32.lib avec un éditeur Hexadécimal, vous trouverez des entrées avec ce format :
_ExitProcess@4
_CreateProcessA@40
Les noms des fonctions sont "affublées d'un tiret de soulignent devant. Le numéro qui le nom de la fonction est la taille totale des paramètres de cette fonction, en octets. ExitProcess prend seulement un paramètre dword, pour que le numéro soit 4. 4 octets = 4 BYTES = 2 WORDS = 1 DWORD.
Pourquoi inclure cette information à propos de la taille des paramètres ? Cette information est employée par MASM pour vérifier si on passe le nombre et la taille correctes des paramètres à une fonction. Vous obtenez cette particularité quand vous appelez cette fonction avec le mot-clé invoke. Si vous poussez seulement des paramètres sur la pile puis exécutez la fonction avec un Call, vous n'obtiendrez pas cette vérification de la part de MASM.
C'est cet avantage supplémentaire qui rend pratiquement impossible la création de Bibliothèque d'importation MASM directement à partir des DLLs, parce que les DLLs ne contient pas d'informations explicites sur la taille des paramètres a passer à leurs propres fonctions.

Création de Bibliothèque d'Importation MASM à partir de DLLs

Si vous désirez pousser des paramètres sur la pile et exécuter des fonctions avec CALL , vous pouvez créer l'import lib' à partir de n'importe quelle DLL pour l'utiliser avec MASM comme cela :
    LIBRARY blah
    EXPORTS
    GetSomeLine
Et voilà ! Vous obtiendrez blah.lib. Vous pouvez l'employer avec MASM tant que vous n'utilisez pas invoke avec les fonctions qui se trouvent dans cet 'importation lib'.

Création d'une Bibliothèque d'Importation MASM, Utilisable avec 'invoke'.

Moi, pour ma part suis peu disposé à utiliser l'approche normale utilisant les 'CALL'. invoke est un emballage agréable pour appeler une fonction. C'est une des raisons pour lesquelles je préfère MASM À TASM. Mais comme je l'ai déjà dis, il est presque impossible de créer des 'importe lib' MASM qui fonctionnent à 100% à partir de chaque DLL. Vous ne pouvez plus utiliser la première méthode pour créer une 'Bibliothèque d'Importation MASM' avec laquelle on puisse utiliser invoke. Par exemple, vous pouvez croire que si vous modifiez les noms des fonctions dans le fichier .def pour inclure "@xx", l'import lib doit être ok. Ayez confiance en moi. Ça ne fonctionnera pas.
La manière simple pour créer "une importe lib invokable" c'est d'employer MASM lui-même. Si vous avez codé une DLL, vous observerez que vous obtiendrez également une 'import lib' pour votre DLL. Et cette 'Import Lib' est entièrement invokable! Notre stratégie consiste à faire ce qui suit :
  1. Obtenez les noms des fonctions et la taille totale de leurs paramètres
  2. Créez le code source de la DLL, ça inclut ses propres fonctions avec le nombre et la taille correctes de leurs arguments à chacunes.
  3. Créez un fichier de définition de module (*.def) qui décrit les fonctions correspondantes dans le code source asm.
  4. Assemblez le code source asm comme un projet de DLL.
Voilà. Vous obtiendrez un Bibliothèque d'Importation MASM entièrement fonctionnelle. Ça ne mérite pas plus d'explications.

Obtenez les noms des fonctions et la taille totale de leurs paramètres

C'est la partie la plus difficile du processus. Si vous avez seulement la DLL, vous vous embarquez dans une aventure fastidieuse. Ci-dessous voici quelques méthodes, mais je pense qu'aucune d'elles ne fonctionne à 100%.

Créer un code source DLL asm qui contient toutes ces fonctions

Après que vous obteniez les noms des fonctions et la taille de leurs paramètres respectifs, le reste est simple. Vous créez juste le squelette d'une DLL asm et ensuite vous créez des fonctions ayant les mêmes noms que celles de la DLL dans le fichier asm. Par exemple, si la DLL a seulement une fonction, GetSomeLine, qui prend des paramètres d'une taille totale de 16 BYTES. Dans le fichier asm, vous tapez les lignes suivantes :
.386
.model flat,stdcall
.code
GetSomeLine proc param1:DWORD, param2:DWORD, param3:DWORD, param4:DWORD
GetSomeline endp
end
Qu'est-ce que c'est que ça ? Vous pouvez vous le demander. Une procédure sans aucune instruction à l'intérieur ? Une Bibliothèque d'Importation ne contenant aucuns renseignements sur ce que l'on suppose que les fonctions devraient faire. Son unique but est de fournir les informations des noms des fonctions ainsi que leurs paramètres. Donc nous n'avons pas besoin de mettre d'instructions dans la procédure fictive. De toute façon, nous nous débarrasserons de la DLL inutile produite par le process assemblé. Tout ce que nous voulons c'est mettre les renseignements des noms des fonctions et la taille des paramètres dans le code asm source pour que MASM puisse produire la Bibliothèque d'Importation qui fonctionne. La taille de chaque paramètre n'est pas essentielle. Pour votre information, actuellement MASM considère toujours chaque paramètre comme un DWORD peu importe quel spécificateur de taille vous employez. Par exemple, nous pouvons employer :
.386
.model flat,stdcall
.code
GetSomeLine proc param1:BYTE, param2:BYTE, param3:BYTE, param4:BYTE
GetSomeline endp
end
Et MASM créera heureusement l'entrée _GetSomeLine@16 dans l'import lib'.

Création un fichier de définition de module

C'est processus simple. Vous avez besoin de ce fichier pour que MASM puisse produire la DLL et la 'Bibliothèque d'Importation (import lib). Le gabarit d'un module de defintion est ainsi fait :
LIBRARY  <Nom de la DLL>
EXPORTS
<Nom de la Fonction>
Vous remplissez juste le nom de la DLL, ce nom servira également pour la Bibliothèque d'Importation (*.lib). Et ensuite on met la liste des noms de fonction en dessous de la ligne EXPORTS, chaque nom étant sur sa propre ligne. Sauvegardez le fichier et vous obtenez le fichier d'un module de défintion fonctionnant.

Assemblez le code source asm comme si c'était une DLL

La dernière étape est la plus simple. Il suffit juste d'utiliser ml.exe et link.exe.
ml /c /coff /Cp blah.asm
link /DLL /NOENTRY /def:blah.def /subsystem:windows blah.obj
Et nous obtenons une 'import lib' invokable.

Un Exemple

L'explication brute au-dessus peut ne pas être très claire. Je suis un ferme partisan de l'apprentissage sur le terrain. Donc je vous fournis un exemple qui montre ce processus. Les fichiers d'exemple sont : L'assemblage de cet exemple vous donnera un kernel32.lib que vous pourrez employer à la place de celui fourni par Microsoft.

Plus d'Outils

Si vous voulez ajouter/enlever des fonctions d'une certaine 'importa lib', vous pouvez employer deux outils assez simple que j'ai codé. Par exemple, si vous voulez ajouter des fonctions non documentées à kernel32.lib, vous trouverez ces outils utiles.

Lib2Def

Il extrait les noms des fonction et la taille de leurs paramètres respectifs de n'importe quelle Bibliothèque d'Importation MASM/VC++. Lancez-le juste et il examinera les process de CHACUNES des bibliothèques d'importation qui se trouvent dans le même dossier. Les fichiers de 'données de sorties' ont des extensions .icz. Leur contenu ressemble à cela :
_ExitProcess@4
_ExitThread@4
_ExitVDM@8
_ExpandEnvironmentStringsA@12
_ExpandEnvironmentStringsW@12   @12
Si vous voulez ajouter une fonction, vous devez juste insérez une nouvelle ligne et mettre un tiret de soulignement, ensuite le nom de fonction puis la taille totale que prennent ses paramètres (en BYTE). Si la fonction est exportée par nombre ordinal, il y aura @xx en plus après le nom. Le "xx" étant le nombre ordinal. Notez que ce simple outil ne vérifie pas les noms de fonctions doubles. Et il peut y avoir des noms doubles dans certaines Bibliothèques d'Importation.

MLib

Cet outil accepte les fichiers de 'données de sorties' de Lib2Def et fabrique des Bibliothèques d'importation à partir d'eux. Il examinera le contenu de CHACUNS des fichiers ayant l'extension .icz. Pour votre information, il fait une analyse syntaxique des lignes qui sont dans les fichiers .icz et crée les fichiers .asm et .def à partir d'eux. Donc il appelle ml.exe et link.exe pour produire la Bibliothèque d'Importation (*.lib). Les fichiers .obj, .asm, .exp et .dll sont ensuite supprimés, il ne reste donc plus que le fichier *.lib. Si cet outil ne réussit pas à produire le fichier .lib, vérifiez s'il vous plaît s'il y a certains noms de fonction doubles dans le fichier .icz : c'est la cause la plus probable d'un éventuel échec.

Downloadez ces deux outils


[Iczelion's Win32 Assembly Homepage]


Traduit par Morgatte