UTILISER LES APIS DE DLLS SANS AVOIR LE FICHIER .LIB

cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 - 15 août 2004 à 04:27
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 - 26 août 2004 à 01:45
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/25400-utiliser-les-apis-de-dlls-sans-avoir-le-fichier-lib

racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
26 août 2004 à 01:45
Salut,
Voici ce que dit Microsoft :
La plupart des applications utilisent la liaison implicite (statique) car c'est la méthode de liaison la plus simple à adopter. Cependant, la liaison explicite (dynamique) est parfois nécessaire. Voici quelques raisons courantes qui justifient l'utilisation de la liaison explicite :
1) L'application ne découvre le nom d'une DLL qu'elle doit charger qu'au moment de l'exécution. Par exemple, l'application peut avoir besoin d'obtenir le nom de la DLL et des fonctions exportées à partir d'un fichier de configuration.
2) Un processus utilisant la liaison implicite est interrompu par le système d'exploitation si la DLL est introuvable au moment du démarrage du processus. Un processus utilisant la liaison explicite n'est pas interrompu dans ce cas et peut essayer de récupérer à partir de l'erreur. Par exemple, le processus peut signaler l'erreur à l'utilisateur et lui demander de spécifier un autre chemin d'accès de la DLL.
3) Un processus qui utilise la liaison implicite est également interrompu si l'une des DLL auxquelles il est lié possède une fonction DllMain qui échoue. Un processus utilisant la liaison explicite n'est pas interrompu dans ce cas.
4) Une application liée de manière implicite à de nombreuses DLL peut être lente à démarrer car Windows charge toutes les DLL en même temps que l'application. Pour accélérer le démarrage, une application peut être liée de manière implicite aux DLL requises immédiatement après le chargement, puis attendre d'être liée explicitement aux autres DLL au fur et à mesure des besoins.
5) Avec la liaison explicite, il n'est plus nécessaire de lier l'application à une bibliothèque d'importation. Si les ordinaux d'exportation changent à la suite de modifications apportées à la DLL, les applications utilisant la liaison explicite n'ont pas besoin d'être rééditées (à supposer qu'elles appellent GetProcAddress à l'aide d'un nom de fonction et non avec une valeur ordinale), alors que les applications utilisant la liaison implicite doivent subir une réédition de leurs liens avec la nouvelle bibliothèque d'importation.
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
25 août 2004 à 17:04
lors d'une déclaration
declare sub ... alias ... lib ... ( ... )
vb6 ne fait rien. par contre au 1er appel d'une des fonctions, la dll est chargée dynamiquement (LoadLibrary) (par une des dll vb6, qui elle est liée statiquement à l'executable) puis la fonction executée. La dll est déchargée a la fin du processus.
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
25 août 2004 à 00:49
c'est possible BlackGoddess que les 2 méthodes aient la même vitesse. Mais alors pourquoi vb6 n'utilise pas une des 2 méthodes et qu'il appelle une api qui appelle une autre api?
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
24 août 2004 à 09:50
également, avec le liage dynamique, l'exportation directe de classes en C++ n'est pas possible.
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
24 août 2004 à 09:48
euh ... dans le cas du liage statique, le nom des dll et de leurs fonctions utilisées sont écrit dans la section importation de l'executable. C'est l'OS qui charge toutes les dll décrites dans la section en meme temps que l'executable, et qui les décharge en meme temps que l'executable (sauf si elles sont partagées, et encore le partage ne marche que sur les NT je crois, bref). Si une dll ou une fonction exportée n'est pas trouvée, l'os met un message d'erreur et ne charge pas l'executable.
Dans le cas du liage dynamique, c'est a l'executable de charger lui meme ses DLLs (LoadLybraryA, FreeLibrary, GetProcAddress). c'est à lui de gérer si une dll n'est pas trouvé également.
A part qu'elle n'est pas chargée au meme moment, c'est la meme chose... (gardons a l'esprit également que kernel32.dll devra probablement etre liée statiquement : en effet, comment appeler LoadLibraryA pour utiliser kernel32.dll si c'est elle meme qui exporte la fonction ?
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
23 août 2004 à 23:36
je suis très septique racpp ... ça va prendre des tests.
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
19 août 2004 à 18:20
Désolé pour la petite faute :)

Je viens d'y apprendre que l'utilisation des ".LIB" et ".h" ne sert qu'à simplifier la programmation et que l'utilisation directe par pointeurs est bien meilleure. Elle permet, entre autres, d'optimiser l'exécutable final pour de meilleures performances. La manière d'appeler les fonctions est identique pour les deux cas.
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
19 août 2004 à 18:14
Salut,
L'idée de l'utilisation des pointeurs pour appeler les fonctions d'une DLL n'est pas nouvelle. Il suffit de regarder le nombre de sources, déposées dans ce site, qui font appel à cette méthode. Ce qui m'a plu dans ton idée c'est le fait de nous avoir rappelé qu'on peut l'utiliser pour se passer des fichiers ".LIB" et ".h" relatifs à une DLL.

A propos de la différence entre les deux méthodes, voici toutes les explications fournies par Microsoft:

http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/vccore/html/_core_link_an_executable_to_a_dll.asp

Je viens d'y apprendre que l'utilisation des ".LIB" et ".h" ne sert qu'à simplifier la programmation et que l'utilisation directe par pointeurs et bien meilleure. Elle permet, entre autres, d'optimiser l'exécutable final pour de meilleures performances. La manière d'appeler les fonctions est identique pour les deux cas.
Voilà à bientôt.
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
18 août 2004 à 21:33
Si tu regarde ton prog avec Depends, tu va voir que l'API que tu a appelé avec mon système n'y est pas donc elle n'est pas dans la genre de table des importations du prog donc je ne sais plus trop... car c'est vrai aussi qu'on l'appelle via le pointeur.
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
17 août 2004 à 20:43
Il fallait écrire par exemple:
int const nombre=10; //nombre de modules à stocker.
HMODULE hmodDlls[nombre];
int count=0;//index 1er élément toujours =0
//count peut varier de 0 à 9.

A propos de la remarque que tu as faite sur ma source, 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 petite source (ou un lien) illustrant la différence entre les deux méthodes. Merci.
A bientôt.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
17 août 2004 à 16:29
le 1er index d'un tableau est elem[0] et non 1.
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
17 août 2004 à 16:27
HMODULE hmodDlls[1];//Dans ce tableau, on stock les modules
int Count=1;//On Commence à 1

hmodDlls[Count]=.....

=>

hmodDlls[1] déclare un tableau a une seule case, accessible par hmodDlls[0]
hmodDlls[Count]=..... (Count = 1) => l'index est en dehors du tableau, tu ne peux pas ecrire ca.
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
17 août 2004 à 16:09
Salut,
J'avoue ne pas avoir encore bien compris. Donne un exemple précis illustrant le problème à résoudre.
A bientôt.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
17 août 2004 à 10:17
Je n'indiquais que le mode d'acces aux tableaux en partant de base ZERO, rien d'autre.
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
17 août 2004 à 06:42
brunews ton idée à l'air bien mais personellement, je déteste les limites(sauf celle du type de donné lui-même). Je crois avoir entendu parler de fonctions avec des noms du genre malloc et ralloc(pas sûre) qui permettent de créer ou de redimensionner un tableau. racpp, je voulais savoir si on pouvait déclarer un type dans le code afin de créer un système genre :

void InitApi(LPCSTR Module, LPCSTR Name, LPCSTR Params[])

qui permettrait d'utiliser les APIs en entrant les paramètres durant l'éxécution du code. ça aurait été plus simple à utiliser.
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
17 août 2004 à 04:13
Salut,
Je viens de poster un source montrant l'intérêt de ton idée DeadlyPredator :
http://www.cppfrance.com/code.aspx?ID=25462

A propos de ta question, je ne suis pas sûr d'avoir bien compris. Mais je peux dire que, à ma connaissance, rien ne permet à un programme, pendant son exécution, de déterminer le type de retour ou le nombre et le type des paramètres d'une fonction d'une DLL. Tout ce qu'il peut savoir, c'est le nombre total des octets des paramètres d'entrée de la fonction. Aucun des moniteurs de DLLs que j'ai testé n'est capable d'afficher ni le nombre ni les types de paramètres d'une fonction exportée de la DLL visionée. S'il existait un moyen, les développeurs de ces utilitaires l'auraient utilisé. Normalement, un programmeur doit être suffisament documenté sur la fonction qu'il veut appeler. Le type d'API sera donc declaré dans le code source. Franchement, je ne vois pas l'intérêt de trouver le nombre ou les types de paramètres d'une fonction qu'on ne connait pas.
J'espère que tout ve que je viens de dire est en rapport avec ta question. Sinon, tu nous précises un peu plus.
A+
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
16 août 2004 à 20:06
Au debut tu as par exemple:
#define MAX 10
int array[MAX];
int count = 0;

Tu ajoutes un elem x:
if(count < MAX) array[count++] = x;

Parcours:
for(int i = 0; i < count; i++) Display(array[i]);

etc...
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
16 août 2004 à 19:44
je suis débutant en cpp. Quand tu dit commence à 0 brunews, tu dit remplir à partir de 0?. Le principe de tableau est que dans celui ci, on stock le chaque dll loadé pour qu'à la fin, on la unload. Je vais étudier ça BlackGoddess...
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
16 août 2004 à 10:28
Fais toujours commencer tes tableaux a 0.
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
16 août 2004 à 10:20
tu peux utiliser de l'asm pour lui construire sa liste d'arguments a la volée


HMODULE hmodDlls[1];//Dans ce tableau, on stock les modules
int Count=1;//On Commence à 1

hmodDlls[Count]=.....

j'ai du mal a comprendre comment le code marche ...
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
16 août 2004 à 06:28
Pour en revenir à ma question, pourrait-on déclarer le type de l'API durant l'Éxécution du code?
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
15 août 2004 à 22:18
DÉSOLÉ je n'y avais pas penser (je suis bête) j'arrange ça tout de suite
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
15 août 2004 à 16:24
Salut tout le monde,
Je viens de tester ce source avec une DLL personelle. Comme tu l'as dit Brunews, ça plante. C'est normal car on appelle une API d'une DLL déja déchargée de la mémoire. Mais l'idée est très bonne. Ces API doivent être initialisées dans le Main (ou WinMain) du code puis leurs DLLs seront déchargées de la mémoire quand on en a plus besoin. Je vais très bientôt poster un source qui donne un exemple montrant l'intéret de cette méthode.
A+
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 août 2004 à 11:24
Salut,

InitializeAPIs();
init les pointeurs de fonction MAIS decharge les librairies de l'adresse referencee par les pointeurs.
Tu appelles ensuite ces fonctions par les pointeurs. Si tu avais teste avec d'autres DLLs que les 3 grosses du kernel qui sont par force deja dans ton espace memoire, c'eut ete le crash a coup sur.
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
15 août 2004 à 06:09
Et j'aurais une question. Est-ce qu'il y aurait moyen de généré le type qui définit la fonction durant l'éxécution du code (sans avoir à utiliser callwindowproc pour appeller l'API)?
DeadlyPredator Messages postés 222 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 30 juin 2008
15 août 2004 à 06:04
OUPS!! désolé, faute de frappe : corrigé
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
15 août 2004 à 04:27
Salut,
Juste un petit truc a corriger: GetTickCount retourne le nombre de milliseconde qui se sont écoulées depuis qu'on a booté l'ordi, pas le nombre de seconde depuis minuit..
Rejoignez-nous