Paramètres réseau directement d'une dll

Soyez le premier à donner votre avis sur cette source.

Snippet vu 7 647 fois - Téléchargée 35 fois

Contenu du snippet

Dans ce source, je reprends l'idée de "DeadlyPredator" pour montrer l'utilité de l'appel direct des fonctions d'une DLL par pointeurs. Voici un exemple de problème résolu grâce à cette méthode:
Pour récuperer l'adresse MAC d'une carte réseau, il y a 3 façons connues mais peu convaicantes:
1- En utilisant le NetBIOS: Nécessite l'installation du partage de fichier et imprimantes.
2- En utilisant l'UUID : Ne fonctionne pas normalement si on a plus d'une interface réseau.
3- En appelant l'API GetAdaptersInfo: Nécessite le téléchargement de la platforme SDK (400 Mo) puis l'installer pour obtenir les fichiers ".h" et ".lib" nécessaires.

La solution idéale est d'appeler directement la DLL du système d'exploitation "iphlpapi.dll". Elle contient toutes les fonctions relatives au paramétrage réseau. Dans ce source, on appelle la fonction GetAdapersInfo() par un pointeur. Pour y arriver, il suffit de définir les structures utilisées, définir le mode d'appel de la fonction , charger la DLL en mémoire et obtenir un pointeur sur la fonction voulue. Cette fonction met tous les paramètres de chaque interface réseau (carte ethernet ou modem) installée sur le système dans une structure spéciale. On récupère ensuite ce qu'on veut de cette structure. Cette solution présente aussi l'avantage d'être compatible avec Windows 98,ME,2000 et XP.
Ce source est pour Visual c++ 6, mais je pense que ça marchera avec les autres compilateurs.

Source / Exemple :


//------------------------------------------------------------------------------------------
// Créer un projet "Console" vide puis copier-coller ce code.

#include <Windows.h>
#include <stdio.h>

//************ DEBUT DEFINITION DES STRUCTURES ****************
//Ce sont des structures standard fournies par Microsoft dans son site MSDN
typedef struct {
    char String[4 * 4];
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;

typedef struct _IP_ADDR_STRING {
    struct _IP_ADDR_STRING* Next;
    IP_ADDRESS_STRING IpAddress;
    IP_MASK_STRING IpMask;
    DWORD Context;
} IP_ADDR_STRING, *PIP_ADDR_STRING;

typedef struct _IP_ADAPTER_INFO {
    struct _IP_ADAPTER_INFO* Next;
    DWORD ComboIndex;
    char AdapterName[260];
    char Description[132];
    UINT AddressLength;
    BYTE Address[8];
    DWORD Index;
    UINT Type;
    UINT DhcpEnabled;
    PIP_ADDR_STRING CurrentIpAddress;
    IP_ADDR_STRING IpAddressList;
    IP_ADDR_STRING GatewayList;
    IP_ADDR_STRING DhcpServer;
    BOOL HaveWins;
    IP_ADDR_STRING PrimaryWinsServer;
    IP_ADDR_STRING SecondaryWinsServer;
    long LeaseObtained; //ici j'ai remplacé "time_t" par "long" pour se passer de "time.h"
    long LeaseExpires;  //idem
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
//************ FIN DEFINITION DES STRUCTURES ****************

int ParamReseau()
{
    //Definir le mode d'appel de fonction par pointeur
    typedef DWORD (WINAPI *PFONCTION)(PIP_ADAPTER_INFO, PULONG);

    //Charger la DLL en mémoire
    HINSTANCE hDLL = LoadLibrary("Iphlpapi.dll");

    //si problème de chargement de la DLL   alors erreur puis quitter
    if(hDLL==NULL)
    {
        printf("%s\n","Erreur chargement iphlp.dll");

        //attendre l'appui sur ENTREE
        printf ("%s","Taper ENTREE pour quitter");
        getchar();
        return 1;
    }

    //Obtenir un pointeur sur la fonction voulue
    PFONCTION GetAdaptersInfo = (PFONCTION) GetProcAddress(hDLL, "GetAdaptersInfo");
    
    //définir le nombre maximum d'interfaces réseau. On peut l'augmenter.
    int const nombre=3;

    //Réserver un tableau pour accueillir les données.
    IP_ADAPTER_INFO infos[nombre];
    
    //Déterminer la taille du tableau en octets
    ULONG taille = sizeof(infos);

    //Déclarer et initialiser un pointeur sur la variable taille
    PULONG ptaille=&taille;
    
    //Appel de la fonction GetAdaptersInfo()
    DWORD retour = GetAdaptersInfo (infos, ptaille);
    
    //Libérer la DLL de la mémoire
    FreeLibrary(hDLL);

    //S'il y'avait erreur alors afficher erreur puis quitter
    if (retour != ERROR_SUCCESS)
    {
        printf("%s\n\n","Aucune information trouvee");

        //attendre l'appui sur ENTREE
        printf ("%s","Taper ENTREE pour quitter");
        getchar();
        return 1;
    }
    
    //Si tout va bien alors afficher les infos a l'ecran
    for(int i=0;i<nombre;i++)
    {
    printf("%s%d\n","  Interface Numero : ",i);
    printf("%s%s\n","         Nom : ",infos[i].Description);
    printf("%s%02X-%02X-%02X-%02X-%02X-%02X\n","     Adresse MAC : ",
         infos[i].Address[0],infos[i].Address[1],infos[i].Address[2],
         infos[i].Address[3],infos[i].Address[4],infos[i].Address[5]);
    printf("%s%s\n","      Adresse IP : ",infos[i].IpAddressList.IpAddress.String);
    printf("%s%s\n","  Masque sous-reseau : ",infos[i].IpAddressList.IpMask.String);
    printf("%s%s\n\n","      Passerelle : ",infos[i].GatewayList.IpAddress.String);

    //s'il n'y a plus d'interface alors sortir de la boucle
    if (infos[i].Next==NULL) break;
    
    }
    
    //attendre l'appui sur ENTREE
    printf ("%s","Taper ENTREE pour quitter");
    getchar();
    return 0;
                
}

void main ()
{
    ParamReseau();
}
//------------------------------------------------------------------------------------------

Conclusion :


Voilà, j'espère n'avoir rien oublié. Très bientôt, je posterai une version plus complète pour Windows. En attendant, vos questions, commentaires, remarques ou critiques sont les bienvenus. A+

A voir également

Ajouter un commentaire Commentaires
Messages postés
1
Date d'inscription
jeudi 18 septembre 2003
Statut
Membre
Dernière intervention
14 juin 2005

La différence entre la lib et l'accès direct est que LoadModule est éxécuté implicitement au chargement du processus. Dans le cas du .lib, celui-ci doit donc "trainer" dans sa mémoire une dll dont l'accès n'est fait qu'une fois, et son temps de chargement sera affecté.
Dans le cas de l'accès direct, il faudra traiter le cas de la dll non présente, et prévoir un bref délai de chargement|déchargement.
Les deux méthode sont bonnes, le développeur choisira donc en fonction de l'application finale.

Sinon : code bon, bien indenté, bien commenté = bonne note.

Merci
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Salut,
C'est une bonne remarque, mais je pense que l'API est toujours appelée directement pendant l'exécution du programme par son adresse mémoire et en passant les paramètres dans la pile. La définition du mode d'appel n'est utile que pour le compilateur. Que ce soit dans un .LIB ou par pointeur le résultat est le même. Mais j'aimerais bien voir l'avis de quelqu'un qui a fait des tests réels pour en avoir le coeur net. Si tu l'as déja fait, donne moi un exemple de petit source (ou un lien) illustrant la différence entre les deux méthodes. Merci.
A bientôt.
Messages postés
222
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
30 juin 2008

C'est vrai que ça fait un bon exemple MAIS n'oublis pas qu'avec ma méthode, l'API ce trouve ralentie car elle n'est pas appellée directement comme c'est le cas quand on a le fichier ".lib".

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.