Chargement de fonction d'une librairie DLL

Chargement de fonction d'une librairie DLL - C++ - Programmation

Marsh Posté le 12-06-2003 à 17:59:08    

Auriez vous quelques informations ou explications à propos des chargements de librairies DLL et de récupération des fonctions contenues dans cette librairie. Je dois être capable d'expliquer ce programme ! C'est le FAR PASCAL et les (FARPROC) Imp_Init=GetProcAddress(hImpDLL, "Imp_Init" );
 
Voici le code complet du petit programme :ange:  

Code :
  1. #include <windows.h>
  2. #include <memory.h>
  3. #include <dos.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #define MAXIMPCARD 8
  8. #define MAXPOLLTAB 50
  9. void (FAR PASCAL *Imp_Init) (short far*,short far*,short far*);
  10. void (FAR PASCAL *Imp_Tx) (short far*,char far*,short far*,short far*,short far*);
  11. void (FAR PASCAL *Imp_Test) (short far*,short far*,short far*,short far*);
  12. void (FAR PASCAL *Imp_String) (short far*,short far*,char far*,short far*,short far*,short far*);
  13. void (FAR PASCAL *Imp_Numeric) (short far*,short far*,short far*,short far*,float far*,short far*,short far*);
  14. void (FAR PASCAL *Imp_ValToByte) (float far*,short far*);
  15. void (FAR PASCAL *Imp_Connect) (unsigned short far*,short far*);
  16. void (FAR PASCAL *Imp_Disconnect) (short far*);
  17. short (FAR PASCAL *Imp_CardInUse) ();
  18. void (FAR PASCAL *Imp_DLLVersion) (char far*);
  19. void (FAR PASCAL *Imp_DLLDelay) (unsigned short);
  20. void (FAR PASCAL *Imp_PowerOff) (short far*);
  21. int LocateCard();
  22. int LoadIMPDrv();
  23. int ImpDrvOK=0;
  24. int ImpCardOK=0;
  25. short CurHand=-1;
  26. unsigned short BaseAddr=0xCA00;
  27. unsigned short CardAddr;
  28. short Poll_Tab[MAXPOLLTAB];
  29. HINSTANCE hImpDLL;
  30. /* Main */
  31. int main()
  32. {
  33.     short CardHandle=-1;
  34.     printf(".: Programme de reconnaissance automatique :.\n\n" );
  35.     ImpDrvOK=LoadIMPDrv();
  36.     if(ImpDrvOK==1)
  37.     {
  38.         printf("Chargement du pilote (IMPDRVR.DLL) --> OK\n\n" );   
  39.        
  40.         ImpCardOK=LocateCard();
  41.         printf("Valeur de retour de LocateCard --> %d\n\n", ImpCardOK); 
  42.         if(ImpCardOK==1)
  43.         {
  44.                 printf("Adresse de la carte %x --> OK\n\n", CardAddr);
  45.         }
  46.        
  47.         if(!Imp_CardInUse()) ImpDrvOK=FreeLibrary(hImpDLL);
  48.         if(ImpDrvOK==1) printf("Liberation du pilote (IMPDRVR.DLL) --> OK\n\n" );     
  49.        
  50.     }
  51.    
  52.    
  53.        
  54.     return 0;
  55. }
  56. /* Chargement du driver */
  57. int LoadIMPDrv()
  58. {
  59.     int LoadStat=0;
  60.  
  61.     hImpDLL=LoadLibrary("IMPDRVR.DLL" );
  62.     if(hImpDLL!=NULL)
  63.     {
  64.         (FARPROC) Imp_Init=GetProcAddress(hImpDLL, "Imp_Init" );
  65.         if(Imp_Init!=NULL)
  66.         {
  67.         (FARPROC) Imp_Tx=GetProcAddress(hImpDLL, "Imp_Tx" );
  68.        
  69.         if(Imp_Tx!=NULL)
  70.         {
  71.         (FARPROC) Imp_Test=GetProcAddress(hImpDLL, "Imp_Test" );
  72.        
  73.         if(Imp_Test!=NULL)
  74.         {
  75.         (FARPROC) Imp_String=GetProcAddress(hImpDLL, "Imp_String" );
  76.        
  77.         if(Imp_String!=NULL)
  78.         {
  79.         (FARPROC) Imp_Numeric=GetProcAddress(hImpDLL, "Imp_Numeric" );
  80.        
  81.         if(Imp_Numeric!=NULL)
  82.         {
  83.         (FARPROC) Imp_ValToByte=GetProcAddress(hImpDLL, "Imp_ValToByte" );
  84.         if(Imp_ValToByte!=NULL)
  85.         {
  86.         (FARPROC) Imp_Connect=GetProcAddress(hImpDLL, "Imp_Connect" );
  87.        
  88.         if(Imp_Connect!=NULL)
  89.         {
  90.         (FARPROC) Imp_Disconnect=GetProcAddress(hImpDLL, "Imp_Disconnect" );
  91.        
  92.         if(Imp_Disconnect!=NULL)
  93.         {
  94.         (FARPROC) Imp_CardInUse=GetProcAddress(hImpDLL, "Imp_CardInUse" );
  95.        
  96.         if(Imp_CardInUse!=NULL)
  97.         {
  98.         (FARPROC) Imp_DLLVersion=GetProcAddress(hImpDLL, "Imp_DLLVersion" );
  99.        
  100.         if(Imp_DLLVersion!=NULL)
  101.         {
  102.         (FARPROC) Imp_DLLDelay=GetProcAddress(hImpDLL, "Imp_DLLDelay" );
  103.       
  104.         if(Imp_DLLDelay!=NULL)
  105.         {
  106.         (FARPROC) Imp_PowerOff=GetProcAddress(hImpDLL, "Imp_PowerOff" );
  107.        
  108.         if (Imp_PowerOff!=NULL)
  109.         {
  110.                 LoadStat=1; /* Flag de chargement correct */
  111.        
  112.         }}}}}}}}}}}}
  113.        
  114.                 if(!LoadStat)
  115.                 {
  116.                                 printf("Erreur de chargement du pilote (IMPDRVR.DLL)\n" );           
  117.                 }
  118.         }
  119.         else
  120.         {
  121.                 printf("Impossible de charger le pilote (IMPDRVR.DLL)\n" );
  122.         }
  123.    
  124.     return (LoadStat);   
  125. }
  126. int LocateCard()
  127. {
  128.     char LpExit=0;
  129.     int AdapFound=0;
  130.     short InitStat=0;
  131.     CardAddr=BaseAddr;
  132.    
  133.     while(!LpExit)
  134.     {
  135.         Imp_Connect(& CardAddr, & CurHand);
  136.         if(CurHand>=0)
  137.         {
  138.                 Imp_Init(& Poll_Tab[0], & InitStat, & CurHand);
  139.                 if(!InitStat)
  140.                 {
  141.                                 LpExit=1;
  142.                                 AdapFound=1;
  143.                 }
  144.                 else
  145.                 {
  146.                                 Imp_Disconnect(& CurHand);
  147.                                 CardAddr+=0x100;
  148.                                 if(CardAddr>0xDFE0) LpExit=2;
  149.                 }
  150.         }
  151.         else
  152.         LpExit=3;
  153.     }
  154.     return (AdapFound);
  155. }


 
 
@ plus  :hello:  
Jardy

Reply

Marsh Posté le 12-06-2003 à 17:59:08   

Reply

Marsh Posté le 12-06-2003 à 19:44:37    

c'est nickel bien codé, parfaitement comprehensible, parfais, rien a dire =)

Reply

Marsh Posté le 12-06-2003 à 19:44:51    

la suite de if la est splendide :)
toutes les variables sont declarées en global, c'est mal.
tu veux savoir quoi exactement ?


Message édité par xWillow le 12-06-2003 à 19:52:20
Reply

Marsh Posté le 12-06-2003 à 21:43:55    

Le truc de FAR PASCAL et GetProcAddress( )
 
Le reste c'est facile, j'aimerais juste des explications sur la déclarations des fonctions. ces même fonctions qui ne sont pas définies dans le code mais dans la librairie ... enfin je crois  :sweat:  :hello:  
 

Reply

Marsh Posté le 12-06-2003 à 23:59:41    

bin y a pas grand chose a dire a part que getprocaddr choppe l'adresse de la fonction.
pour le FAR PASCAL je suis meme pas sur que ce soit necessaire
 
edit: je rectifie c'est sans doute utile mais je sais pas comment ca fonctionne


Message édité par xWillow le 13-06-2003 à 00:01:30
Reply

Marsh Posté le 13-06-2003 à 08:07:31    

ls PASCAL me semble que c'est un #define de _stdcall qui est la convention d'appel de fonction. tu peux effectivement t'en passer si ta fonction retourne char/short/int/void/float/double et ne prends pas de param sinon ca peut mener a des pb. (Si la fonction dans ta dll est declaré avec __stdcall / PASCAL et que tu l'utilises sans (c a d avec _cdecl) ca va merder)
 
le FAR je sais pas


Message édité par chrisbk le 13-06-2003 à 08:07:57
Reply

Marsh Posté le 13-06-2003 à 08:46:17    

dans la lib de vc++ ou c'etait déclaré, j'ai vu
#define FAR
donc il servait a rien ...


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 13-06-2003 à 08:48:29    

BlackGoddess a écrit :

dans la lib de vc++ ou c'etait déclaré, j'ai vu
#define FAR
donc il servait a rien ...


 
ca doit etre un relicat des temps ancien alors :D

Reply

Marsh Posté le 13-06-2003 à 10:21:14    

chrisbk a écrit :


 
ca doit etre un relicat des temps ancien alors :D


 
Exact. ça vient du 16Bits, ou il y avait des pointeur distants et ds pointeurs locaux, un truc dans l'genre.

Reply

Marsh Posté le 16-06-2003 à 10:19:17    

Ce que je comprends pas c'est
 
--> void (FAR PASCAL *Imp_Init) (short far*,short far*,short far*);
Alors ça c'est la déclaration ...
 
ainsi que
--> (FARPROC) Imp_Init=GetProcAddress(hImpDLL, "Imp_Init" );
Et ça c'est la récupération de l'adresse dans la DLL ...
 
J'aimerais comprendre ces espèces de type bizarres
FAR PASCAL et FARPROC

 
Merci pour les renseignements  :hello:  :bounce:

Reply

Marsh Posté le 16-06-2003 à 10:19:17   

Reply

Marsh Posté le 16-06-2003 à 10:49:38    

Ca date des Win 3.1 ca.
C'était du 16 bits. Y'avait 2 type de pointeur : les 16 bits (OFFSET), qui limitent à 64Ko, et les pseudo 32 bits (SEGMENT + OFFSET), pseudo cas si c'était bien codé sur 32 bits, c'est pas comparable au 32 bits actuels. On avait droit à 1Mo. Ce dernier pointeur étaient des pointeur FAR (nécessitent un FAR CALL au niveau assembleur).
Voilà pour le FAR. Dès que ton exe fait + de 64Ko, il faut des pointeur FAR sur tes fonctions. Comme on charge des dll, situées dans un autre segment de code, => pointeur FAR.
Après, PASCAL c'est une convention d'appel comme te l'a dit chrisbk.
Ca été abandonné parce que, je crois, PASCAL est toujours __stdcall, alors que WINAPI peut être différent (sous Mac notamment), ou éventuellement, être un jour différent.
 
Je viens de jeter un oeil à windef.h :

Code :
  1. #ifdef _MAC
  2.     #define CALLBACK    PASCAL
  3.     #define WINAPI      CDECL
  4.     #define WINAPIV     CDECL
  5.     #define APIENTRY    WINAPI
  6.     #define APIPRIVATE  CDECL
  7.     #ifdef _68K_
  8.         #define PASCAL      __pascal
  9.     #else
  10.         #define PASCAL
  11.     #endif
  12. #elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
  13.     #define CALLBACK    __stdcall
  14.     #define WINAPI      __stdcall
  15.     #define WINAPIV     __cdecl
  16.     #define APIENTRY    WINAPI
  17.     #define APIPRIVATE  __stdcall
  18.     #define PASCAL      __stdcall
  19. #else
  20.     #define CALLBACK
  21.     #define WINAPI
  22.     #define WINAPIV
  23.     #define APIENTRY    WINAPI
  24.     #define APIPRIVATE
  25.     #define PASCAL      pascal
  26. #endif


 
Bon ben PASCAL est différent selon les sytèmes alors. Je sais pas pourquoi ils ont changé PASCAL pour WINAPI, peut être simplement pour le style.
Voila. J'espère ne pas avoir trop dit de betises vu que j'ai jamais codé sous Win 3x (notamment, je sais pas comment ca se passe pour les 286). Mais en gros ca doit etre ca.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 16-06-2003 à 14:29:52    

Bien sympathique ces explications ... Je te remercie :sol:

Reply

Marsh Posté le 16-06-2003 à 17:15:50    

le FAR "peut" être toujours valable, car étant en mode protégé, tu peux avoir des appels inter-segment via des adresse 16:32 bits (alignées sur 64 bits il me semble, donc 16 bits de perdus).  
 
mais je sais pas si ça se passe au niveau du code compilé pour l'appli, les DLL systèmes, ou le code exécuté par le vecteur d'interruption pour sauter au noyau...
 
après pour être sûr, il faudrait savoir de quoi viens le source... (appli win16 ou win32 ?, vu le code c'est du win16)


Message édité par bjone le 16-06-2003 à 17:23:33
Reply

Marsh Posté le 16-06-2003 à 18:48:19    

Appel inter-segment en 32 bits ?
Je croyais qu'il fallait être privilégié pour changer la valeur d'un registre de (descipteur de) segment ... ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 17-06-2003 à 10:34:19    

c ptet (oups) possible, j'ai jamais essayé encore...
 
mais chose sûr, tu ne peux pas changer vers un sélecteur (segment) dont le niveau de privilège est plus haut.
 
mais peut être que dans les API bas-niveau, il possible de créer plusieurs segment de donnée pour avoir plus de ressources (vu qu'un process win32 a 2Go de données par défaut (les 2Go supérieures sont mappées vers le code des DLLs je crois), et qu'il faut compiler avec une option spéciale pour pouvoir avoir 3Go.
 
Donc dans le cas ou on aurait plus de 4Go de ram avec windows en mode PAE, je pense qu'ils ont dû laisser la possiblité d'avoir plusieurs segments de données  :??:  :) (je vais faire un tour dans la MSDN, vu que j'aimerai bien savoir ce qu'il est possible de faire à ce niveau)


Message édité par bjone le 17-06-2003 à 11:25:21
Reply

Marsh Posté le 17-06-2003 à 10:36:52    

parallèlement je sais (dumoins crois) que sous les noyaux NT, le kernel n'utilise que deux niveau de privilèges (le ring 0 pour le noyau, et le 3 je crois pour les applis), mais par exemple OS/2 utilise les 4 niveaux de privilèges du mode protégé x86 (0 pour le kernel, 1 pour les drivers bas-niveau, 2 pour les "services", et le 3 pour les process utilisateur).

Reply

Marsh Posté le 17-06-2003 à 10:54:07    

héhé je crois que j'ai trouvé une coquille chez crosoft:
http://msdn.microsoft.com/library/ [...] pre_47.asp

Reply

Marsh Posté le 17-06-2003 à 11:20:53    

bon apparement y'a pas moyen de créer plusieurs segment de donnée, pour le mode PAE c'est une fenêtre qui est mappée par le mmu pour attendre la mémoire au dessus des 4 Gos....
 
http://www.winntmag.com/Articles/I [...] 1&show=685
 
http://msdn.microsoft.com/library/ [...] nsions.asp
 

Reply

Marsh Posté le 17-06-2003 à 15:25:28    

Je confirme c'est un extrait de code d'une application win16 sous win3.1

Reply

Marsh Posté le 17-06-2003 à 17:06:16    

ok c'est bien ce que je pensais...
 
tu comptes l'utiliser via une appli win16, ou tout refaire pour le win32 ? (pb dans le cas d'un windows nt)

Reply

Marsh Posté le 17-06-2003 à 18:36:13    

L'executable compilé marche parfaitement sous WinNT je bosse sur cet OS  :sweat:

Reply

Marsh Posté le 23-06-2003 à 13:25:30    

qq1 saurait ou trouver des cours sur le chargement des dll, sur le systeme, sur le vecteur d'interruption, les registres, etc ?
 
parce que ca m'interresse bcp, mais c du chinois pour moi tout ca ...
(plutot sous noyau nt5 si possible, mais reprendre plus tot depuis win16 m'interresse aussi :) )


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 23-06-2003 à 13:26:40    

tu veux savoir faire ca en C ? (eg charger une DLL )  
paske c pas bien compliqué, genre 4 fonctions :D

Reply

Marsh Posté le 23-06-2003 à 13:44:20    

non, independemment du c, je voudrais savoir comment ca fonctionne (par exemple est-ce le noyau qui charge une dll ? ou est-elle chargée ? etc)


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 23-06-2003 à 17:44:39    

Y'a des bouquins là dessus. Pour des infos sur le fonctionnement des dll, tu peux chercher de la doc sur le format PE. Tu verras le chargement des dll, l'édition dynamique des liens, la rellocation, ...


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 23-06-2003 à 18:44:54    

qq1 aurait une url ? ou une référence de bouquin ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 23-06-2003 à 18:45:21    

je me suis un peu documenté sur le format PE, mais je voudrais creuser plus profondement le sujet


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 24-06-2003 à 10:00:20    

Reply

Marsh Posté le 24-06-2003 à 13:42:37    

mci :)


---------------
-( BlackGoddess )-
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed