PROCÉDURE : Appeler le code à 16 bits depuis le code à 32 bits sous Windows 95, Windows 98 et Windows Me

Traductions disponibles Traductions disponibles
Numéro d'article: 155763 - Voir les produits auxquels s'applique cet article
Ancien nº de publication de cet article : F155763
Agrandir tout | Réduire tout

Sommaire

Résumé

Les développeurs pourraient avoir besoin d'accéder à la fonctionnalité offerte par une bibliothèque de liaison dynamique (DLL) 16 bits depuis une application Win32. Cette situation se présente notamment lorsqu'ils ne disposent pas du code source de la DLL pour pouvoir le porter vers Win32. Cet article explique le mécanisme permettant aux DLL 32 bits d'appeler des DLL 16 bits. Ce mécanisme de conversion s'appelle un " thunk " et la méthode de mise en oeuvre sous Microsoft Windows 95, Windows 98 et Windows Millennium Edition s'appelle un " thunk plat ".

La procédure suivante présente les trois grandes étapes de la création d'un thunk plat :
  1. Créez le script du thunk.
  2. Générez la DLL 32 bits.
  3. Générez la DLL 16 bits.

Plus d'informations

Un thunk plat se compose d'une DLL 32 bits et d'une DLL 16 bits qui fonctionnent ensemble. Une application Win32 appelle la DLL 32 bits, qui appelle une fonction importée dans la DLL 16 bits. Une fois la fonction dans la DLL 16 bits revenue, elle retourne vers la DLL 32 bits, qui à son tour repart vers l'application Win32. Les DLL 32 bits et 16 bits fonctionnent en appelant les noyaux à 32 bits et à 16 bits de Windows 95 pour traiter tous les détails de niveau inférieur nécessaires pour effectuer la transition du code 32 bits en code 16 bits et vice-versa.

La conception d'un thunk plat nécessite la création d'un script de thunk (fichier .thk). Ce script se compile à l'aide du compilateur de thunks en un fichier en langage assembleur, qui est alors assemblé deux fois : une fois avec chaque indicateur de -DIS_32 et -DIS_16. Ceci vous permet de créer à la fois les modules d'objets à 32 bits et 16 bits. Ces modules d'objets sont respectivement liés aux DLL 32 bits et 16 bits. Le diagramme suivant récapitule les fichiers nécessaires à la création des DLL :
                         +------------+
                         | 32to16.thk |
                         +------------+
                               |
                         +------------+
                         | 32to16.asm |
                         +------------+
                           /         \ 
                  -DIS_32 /           \ -DIS_16
                        /              \ 
                  +-----------+  +-----------+
                  | 32THK.obj |  | 16THK.obj |
                  +-----------+  +-----------+
                        /                 \ 
        +-------+    +-------+             +-------+
        | APP32 | -> | DLL32 | -- THUNK -- | DLL16 |
        +-------+    +-------+             +-------+

Outils nécessaires à la création de thunks plats

  • Compilateur Microsoft Visual C++ version 1.5x (16 bits) pour le côté 16 bits de la création du thunk. Le côté 16 bits du thunk est une DLL 16 bits.
  • Compilateur Microsoft Visual C++ version 2.0x (32 bits) pour le côté 32 bits de la création du thunk. Le côté 32 bits du thunk est une DLL 32 bits.
  • Compilateur de thunks (Thunk.exe) du Kit de développement (SDK) de Microsoft Win32 pour la compilation des scripts du thunk.
  • Microsoft Macro Assembler (MASM) version 6.1 ou supérieure pour l'assemblage de la sortie en langage assembleur du compilateur de thunks.
  • Fichier Rc.exe 16 bits du répertoire BINW16 du SDK de Microsoft Win32 pour le marquage de la DLL de thunk 16 bits en tant que version 4.0.

Création du script du thunk

Vous devez créer un script dont le compilateur de thunks peut se servir pour créer un thunk. Un script de thunk est un fichier texte qui contient des définitions de types, des prototypes de fonctions à appeler par l'intermédiaire des thunks et la spécification de la direction des paramètres de chaque fonction. Par exemple, certaines fonctions exigent à la fois des paramètres d'entrée et de sortie, tandis que d'autres nécessitent uniquement des paramètres d'entrée. Les scripts de thunk utilisent une syntaxe spéciale pour décrire s'il s'agit de paramètres d'entrée, de sortie ou les deux à la fois.

Un script de thunk pour la conversion de 32 bits en 16 bits commence par l'instruction suivante :
enablemapdirect3216 = true;
Le compilateur de thunks s'attend à ce que le côté 32 bits du thunk soit déclaré sous la forme __stdcall et que le côté 16 bits soit __far __pascal (la déclaration WINAPI se charge de cela des deux côtés). Les conventions d'appel __cdecl et __fastcall ne sont pas prises en charge par le compilateur de thunks. Cependant, notez que le compilateur de thunks n'accepte pas les mots clés __far, __pascal ou __stdcall, qui sont admis.

L'exemple suivant illustre un script de thunk pour une fonction sans paramètres :
   enablemapdirect3216 = true;

   void MyThunk16()
   {
   }
La déclaration équivalente serait alors :
   Langage C :  void WINAPI MyThunk16(void);
   Langage C++ :  extern "C" void WINAPI MyThunk16();
L'exemple de script ci-dessous présente une fonction qui accepte deux paramètres et renvoie une valeur. Le deuxième paramètre est un paramètre de sortie qui contient un pointeur de nouveau transmis à la DLL 32 bits.
   enablemapdirect3216 = true;

   typedef int   BOOL;
   typedef char *LPSTR;

   BOOL MyThunk16(LPSTR lpstrInput, LPSTR lpstrOutput)
   {
      lpstrInput  = input;    // facultatif ; la valeur par défaut est input
      lpstrOutput = output;
   }
L'instruction " lpstrOutput = output " indique au compilateur de thunks que la fonction 16 bits renvoie une adresse à convertir d'un pointeur selector:offset en adresse linéaire à 32 bits.

Le script de thunk ci-dessous utilise des types de paramètres plus complexes, tels que des structures. Cet exemple montre également comment spécifier des paramètres d'entrée et de sortie.
   enablemapdirect1632 = true;

   typedef unsigned int UINT;
   typedef char *LPSTR;

   typedef struct _POINT {
      UINT x;
      UINT y;
   }POINT, *LPPOINT;

   typedef struct _CIRCLE {
      POINT center;
      UINT  radius;
   }CIRCLE, *LPCIRCLE;

   void MyThunk32( LPCIRCLE lpCircleInOut)
   {
      lpCircleInOut = inout;
   }
L'instruction " lpCircleInOut = inout " indique au compilateur de scripts que ce pointeur va servir aux entrées et sorties. Le compilateur de thunks convertit alors lpCircleInOut d'une adresse linéaire à 32 bits en pointeur selector:offset lors de l'appel de la fonction, puis de nouveau en adresse linéaire à 32 bits au retour de la fonction. La conversion est traitée par le thunk créé par le compilateur de thunks.

Utilisation du compilateur de thunks

Le compilateur de thunks s'utilise comme suit :
thunk.exe /options <fichier_entrée>-o <fichier_sortie>
La ligne de commande suivante montre comment compiler un script de thunk 32 bits en 16 bits. Cette ligne concerne un script de thunk appelé 32to16.thk et produit un fichier en langage assembleur appelé 32to16.asm.
thunk -t thk 32to16.thk -o 32to16.asm
L'option " -t thk " indique au compilateur de thunks d'ajouter le préfixe " thk_. " devant les fonctions de thunk dans le fichier en langage assembleur. Ce préfixe est utilisé lors de la liaison de plusieurs scripts de thunk sous forme d'une paire de DLL et sert à créer une paire de DLL qui contient à la fois des thunks de conversion 32 bits en 16 bits et 16 bits en 32 bits. Chaque script de thunk doit posséder un préfixe unique.

Génération de la DLL 32 bits

  1. Dans la fonction DllMain de la DLL 32 bits, vous devez appeler une fonction créée par le compilateur de thunks, appelée thk_ThunkConnect32, car chaque raison (dwReason) DllMain est appelée, comme illustré ici (" thk " est le préfixe du commutateur -t du compilateur de thunks) :
          // prototype de la fonction dans le fichier .obj du script de thunk
          BOOL WINAPI thk_ThunkConnect32(LPSTR     lpDll16,
                                         LPSTR     lpDll32,
                                         HINSTANCE hDllInst,
                                         DWORD     dwReason);
    
          BOOL WINAPI DllMain(HINSTANCE hDLLInst,
                              DWORD     dwReason,
                              LPVOID    lpvReserved)
          {
             if (!thk_ThunkConnect32("DLL16.DLL", "DLL32.DLL",
                                     hDLLInst, dwReason))
             {
                return FALSE;
             }
             switch (dwReason)
             {
                case DLL_PROCESS_ATTACH:
                   break;
    
                case DLL_PROCESS_DETACH:
                   break;
    
                case DLL_THREAD_ATTACH:
                   break;
    
                case DLL_THREAD_DETACH:
                   break;
             }
             return TRUE;
          }
  2. Insérez les lignes suivantes dans la section EXPORTS du fichier de définition du module (.def ) pour la DLL 32 bits. Par exemple :
          
       thk_ThunkData32
  3. Exportez les fonctions que l'application Win32 appelle. Vous pouvez soit utiliser le fichier de définition du module (.def) de la DLL 32 bits, soit le mot clé __declspec(dllexport). Assurez-vous que les fonctions sont déclarées et définies en tant que __stdcall (ou WINAPI). Si la DLL 32 bits est écrite en C++, veillez également à déclarer les fonctions en tant que " C " externe.
  4. Compilez le script de thunk comme suit (s'il n'est pas déjà compilé) :
          thunk -t thk 32to16.thk -o 32to16.asm
  5. Assemblez le fichier en langage assembleur généré par le compilateur de thunks sous la forme d'un module d'objet à 32 bits. Par exemple :
          ml /DIS_32 /c /W3 /nologo /coff /Fo thk32.obj 32to16.asm
  6. Liez ce module d'objet à la DLL 32 bits.
  7. Liez la bibliothèque Thunk32.lib à la DLL 32 bits. Il s'agit de la bibliothèque d'importation 32 bits fournie par le SDK de Win32, qui contient les références à l'API de conversion 32 bits que le code créé par le compilateur de thunks utilise.

Génération de la DLL 16 bits

  1. La DLL 16 bits doit exporter une fonction appelée DllEntryPoint. Cette fonction doit appeler une fonction créée par le compilateur de thunks, appelée thk__ThunkConnect16 (" thk " est le préfixe du commutateur -t du compilateur de thunks), lors de chaque appel de DllEntryPoint :
          // prototype de la fonction dans le fichier .obj du script de thunk
          BOOL WINAPI __export thk_ThunkConnect16(LPSTR lpDll16,
                                                  LPSTR lpDll32,
                                                  WORD  hInst,
                                                  DWORD dwReason);
    
          BOOL WINAPI __export DllEntryPoint(DWORD dwReason,
                                             WORD  hInst,
                                             WORD  wDS,
                                             WORD  wHeapSize,
                                             DWORD dwReserved1,
                                             WORD  wReserved 2)
          {
             if (!thk_ThunkConnect16("DLL16.DLL",
                                     "DLL32.DLL",
                                     hInst,
                                     dwReason))
             {
                return FALSE;
             }
             return TRUE;
          }
  2. Insérez les lignes suivantes dans la section IMPORTS du fichier de définition du module (.def) pour la DLL 16 bits. Par exemple :
          C16ThkSL01      = KERNEL.631
          ThunkConnect16  = KERNEL.651
  3. Insérez les lignes suivantes dans la section EXPORTS du fichier de définition du module (.def) pour la DLL 16 bits. THK_THUNKDATA16 est défini dans le fichier d'objet assemblé à partir de la sortie du compilateur de thunks. Ces deux symboles doivent comporter le mot clé RESIDENTNAME, mais peuvent également avoir n'importe quel nombre ordinal.
          THK_THUNKDATA16 @1  RESIDENTNAME
          DllEntryPoint   @2  RESIDENTNAME
  4. Ajoutez les fonctions de thunk à l'instruction EXPORTS du fichier de définition du module de la DLL (.def) 16 bits. Assurez-vous que les fonctions sont déclarées et définies en tant que __far __pascal __export (ou WINAPI __export). Si la DLL est écrite en C++, veillez également à les déclarer en tant que " C " externe. Le côté 32 bits du thunk appelle ces fonctions.
  5. Compilez le script de thunk comme suit (s'il n'est pas déjà compilé) :
          thunk -t thk 32to16.thk -o 32to16.asm
  6. Assemblez le fichier en langage assembleur généré par le compilateur de thunks sous la forme d'un module d'objet à 16 bits. Par exemple :
          ml /DIS_16 /c /W3 /nologo /Fo thk16.obj 32to16.asm
  7. Liez ce module d'objet à la DLL 16 bits.
  8. Marquez la DLL 16 bits en tant que version 4.0. Pour ce faire, utilisez le compilateur de ressources (Rc.exe). La ligne suivante indique la syntaxe à respecter :
    rc -40 <fichier DLL>
    L'option -40 est disponible dans le compilateur de ressources livré avec le SDK de Win32.

    REMARQUE : veillez à utiliser le fichier Rc.exe figurant dans le répertoire BINW16 pour que la DLL soit marquée en tant que version 4.0. Le fichier Rc.exe inclus dans les versions 16 bits de Microsoft Visual C++ ne marque pas la DLL en tant que version 4.0.

Références

Pour plus d'informations sur le débogage des thunks plats, reportez-vous à l'article suivant de la Base de connaissances Microsoft :
133722 PROCÉDURE : Déboguer les thunks plats

Propriétés

Numéro d'article: 155763 - Dernière mise à jour: lundi 11 juillet 2005 - Version: 1.6
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Win32 Application Programming Interface sur le système suivant
    • Microsoft Windows 95
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
    • Microsoft Platform Software Development Kit-January 2000 Edition
Mots-clés : 
kbhowto kbtshoot kbsdkplatform kbapi kbdss kbnetwork kbprogramming kbkernbase kbthunks kbnetapi kbgrpdsnet kbgrpdskernbase KB155763
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com