IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

La fonction GetProcAddress


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut La fonction GetProcAddress
    Bonjour,

    J'ai déjà eu plusieurs fois à faire face à cette fonction, qui s'utilise très simplement.

    Seulement dans un souci de progression, j'aimerai avoir plus de détail sur le fonctionnement de cette fonction.

    1 - Comment cette fonction s'y prend pour retrouver l'adresse d'une fonction ?

    2 - En recherchant des infos sur la doc microsoft, j'ai lu que cette fonction était utilisé lors d'un lien explicite à une library. ( Ce qui paraît à première vu logique. ) Ce qui m'amène à me poser la question, comment fonctionne un lien implicite?

    Alors techniquement on inclut le header qui contient les définitions, ainsi que la library dite statique, qui permet de faire les liens sur les fonctions. Mais concrètement... Les fonctions sont incluses directement au linkage de l'application? Ou alors les liens sont en dur ( autrement dis, l'adresse des fonctions est défini à la compilation, et l'application doit se débrouiller pour dire au loader de charger les library aux endroit prévu ) ?

    3 - La réponse à cette question, découlera de la question 2. Comment notre programme connaît l'adresse de GetProcAddress? Pour qu'il en soit ainsi, je dirais que la library Kernel32.dll, doit toujours être chargé à la même adresse mémoire. Ou peut être existe-t-il une méthode que je ne soupçonne pas?


    Merci beaucoup à qui pourra me faire ( ou tenter ) de me faire progresser sur ce sujet!

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Euh pour ma première question, voilà la réponse qui me vient à l'esprit.

    On appelle LoadLibrary, qui nous retourne un handle sur la library où se trouve notre fonction.

    Ensuite viens GetProcAddress, qui d'après l'handle trouve la library en mémoire. Ensuite je suppose qu'il doit exister ( créée lors de la compilation de la Dll ) une sorte de table qui associe nom de la fonction et offset.

    A partir de là, la fonction GetProcAddress, peut retrouver l'adresse mémoire de la fonction.

    Je fais une erreur?

  3. #3
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par klakman Voir le message
    1 - Comment cette fonction s'y prend pour retrouver l'adresse d'une fonction ?
    C'est tout simplement en cherchant ladite fonction (enfin, son nom) dans la table des fonctions exportées de la DLL.

    Citation Envoyé par klakman Voir le message
    2 - En recherchant des infos sur la doc microsoft, j'ai lu que cette fonction était utilisé lors d'un lien explicite à une library. ( Ce qui paraît à première vu logique. ) Ce qui m'amène à me poser la question, comment fonctionne un lien implicite?
    Un lien implicite, c'est un lien contenu dans l'exécutable lui-même (dans la table de relocation, je crois). En gros, ton éditeur de liens a mis l'information directement dans l'exécutable, en disant "telle fonction est dans telle DLL". C'est en parcourant ces sections de l'exécutable qu'un programme comme Dependancy Walker t'affiche toutes les DLL liées implicitement à ton exécutable.

    Citation Envoyé par klakman Voir le message
    Ou alors les liens sont en dur ( autrement dis, l'adresse des fonctions est défini à la compilation, et l'application doit se débrouiller pour dire au loader de charger les library aux endroit prévu ) ?
    Les liens sont "symboliques" : c'est un nom de fonction plus un nom de DLL qui est inclus dedans. La DLL est chargée, et la fonction linkée, lors du chargement de l'exécutable, et AVANT le début de son exécution.

    Dans tous les cas, c'est le système d'exploitation lui-même qui reconstruit les liens implicites (on dit aussi "statiques") lors du chargement de l'exécutable. Tu n'appelles donc pas toi-même GetProcAddress, et, en fait, le système non plus, il utilise des mécanismes internes bien plus rapides qui font la même chose, mais sans les sécurités inhérentes à un appel fait par l'utilisateur.

    Le problème d'un lien implicite/statique, c'est que si une des DLL manque, ton programme ne s'exécute pas DU TOUT, car c'est la construction de l'image-mémoire qui a échoué. L'exécutable ne l'est donc pas, pour le système d'exploitation.

    Un lien explicite/dynamique, lui, est fait par l'utilisateur "sur demande". En conséquence, si la DLL est introuvable, il peut décider d'utiliser une méthode de secours, ou bien d'inactiver la fonctionnalité. Le programme continue quand même à fonctionner, même si c'est de façon dégradée.

    Quant à "comment GetProcAddress" trouve ladite adresse, c'est très simple : l'appel à "LoadLibrary" a chargé la DLL en mémoire. Lors de ce chargement, le système d'exploitation a créé une table de toutes les fonctions exportées, et il connait donc leur adresse en mémoire. Voilà pourquoi GetProcAddress a besoin du handle retourné par LoadLibrary pour fonctionner.

    Citation Envoyé par klakman Voir le message
    3 - La réponse à cette question, découlera de la question 2. Comment notre programme connaît l'adresse de GetProcAddress? Pour qu'il en soit ainsi, je dirais que la library Kernel32.dll, doit toujours être chargé à la même adresse mémoire. Ou peut être existe-t-il une méthode que je ne soupçonne pas?
    Il est très difficile de réaliser un programme Windows qui ne dépende pas de certaines DLL... Notamment "Kernel32" et "NtDll", ainsi que "User32" et "Gdi32" pour les programmes graphiques.
    Ton compilateur crée automatiquement ces dépendances quand tu inclus certaines entêtes et/ou que tu utilises certaines fonctions (comme GetProcAddress, justement).

    Et, comme je l'ai dit plus haut, à ce stade ce n'est plus l'API Win32 qui fonctionne, mais le système d'exploitation lui-même. Bien sûr, il effectue quelque chose de très similaire à GetProcAddress, mais de façon totalement interne, très rapide et (malheureusement) sans gestion évoluée des erreurs : soit TOUT marche, soit ton exécutable est rejeté et ne se lancera donc pas.



    Le choix entre link statique et dynamique peut se résumer ainsi :

    Liens statiques :
    • + : Facilité d'ajout d'une DLL (rien à faire d'autre que cocher une case de dépendance, ou ajouter un .LIB).
    • + : Les dépendances de l'exécutables sont clairement connues dès la compilation terminée.
    • + : Possibilité d'importer des classes, variables, etc. librement.
    • - : Impossibilité de lancer l'exécutable si une DLL liée statiquement est manquante.
    • - : Quasi-impossible de lier statiquement une DLL si l'on n'a pas la librairie d'importation correspondante, ce qui est quasiment toujours le cas si la DLL n'a pas été faite avec Visual C++.


    Liens dynamiques :
    • + : Possibilité de lancer l'exécutable même avec des DLL manquantes.
    • + : Possibilité de lier des DLL écrites dans d'autres langages (sous réserve de conventions d'appel adéquates toutefois).
    • - : Quasi-impossible d'importer des classes C++ de cette manière, seulement des fonctions.
    • - : Beaucoup de travail d'écriture pour importer une DLL de taille significative.
    • - : Les dépendances d'un exécutable ne tiennent jamais compte des DLL liées dynamiquement, il n'est donc pas possible de savoir facilement quelles sont ses dépendances.


    On pourrait croire que les liens dynamiques n'ont que des inconvénients... Sauf que, justement, les deux avantages que cela procure sont cruciaux sur certains projets, car c'est la base de fonctionnement (par exemple) des plug-ins, ou la seule façon d'interfacer le C/C++ avec des langages très différents (code Fortran, Pascal, Visual Basic, d'un autre compilateur C, etc.).
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Encore une fois merci pour ces explications claires et complètes sur le sujet.

    Une dernière chose, quand tu dis que lors d'un lien implicite, le système fait appelle à un mécanisme interne.
    Un nom de fonction? Ou alors ce n'est pas documenté?

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par klakman Voir le message
    Un nom de fonction? Ou alors ce n'est pas documenté?
    C'est interne au système d'exploitation. Il y a sûrement un nom de fonction, mais non seulement tu n'as pas besoin de le connaître, mais plus important : tu ne dois jamais tenter de l'utiliser, car la fonction peut changer de nom, de prototype, de "tout" sans préavis.

    En effet, dans un OS, l'éditeur dudit système d'exploitation s'engage à maintenir au maximum possible l'interface "publique" de l'OS, afin que les programmes continuent de fonctionner... Mais en aucun cas il ne garantit quoi que ce soit sur les éléments internes. Tenter de les utiliser, c'est donc de fortes chances de crasher plus ou moins définitivement ton système.

    Sous Linux, par exemple, c'est documenté, ça ne l'est pas sous Windows. Mais dans les deux cas : "pas touche !"...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Ok, merci pour tout.

  7. #7
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Et, comme je l'ai dit plus haut, à ce stade ce n'est plus l'API Win32 qui fonctionne, mais le système d'exploitation lui-même. Bien sûr, il effectue quelque chose de très similaire à GetProcAddress, mais de façon totalement interne, très rapide et (malheureusement) sans gestion évoluée des erreurs : soit TOUT marche, soit ton exécutable est rejeté et ne se lancera donc pas.
    Il existe aussi un mode hybride proposé par VC++ au moins : le delay loading.
    http://msdn.microsoft.com/en-us/libr...90(VS.80).aspx
    C'est seulement quand tu appelles la fonction pour la première fois que le linkage est fait. S'il échoue, une exception système (SEH) est lancée, et tu peux la capturer pour continuer à fonctionner. J'avoue ne pas savoir si c'est une fonctionnalité au niveau OS (loader de Windows) ou VC++. Je pense que c'est la seconde.

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Aurelien.Regat-Barrel Voir le message
    J'avoue ne pas savoir si c'est une fonctionnalité au niveau OS (loader de Windows) ou VC++.
    Purement VC++, très exactement comme les librairies d'importation qui permettent d'importer des classes depuis une DLL (opération normalement impossible au vu du format des DLL Windows) grâce à un "hack" de la VMT des objets : la VMT est remplie via des GetProcAddress directement...
    Le même genre de trucs est utilisé pour importer des variables : la "fonction" dans la DLL n'en est pas vraiment une, mais son adresse pointe vers la variable exportée.

    A noter que non seulement ce genre de choses ne fonctionne que depuis VC++ avec des DLL compilées avec VC++, mais qu'en plus, cela empêche l'utilisation de la DLL avec pas mal d'autres compilateurs, inclus les autres compilateurs C/C++...

    Sur VC++, cette fonctionnalité sert à avoir un linkage statique de la DLL tout en tolérant l'absence de la DLL sur le système. En temps normal, une DLL linkée statiquement et absente du système empêche le programme de démarrer, même en mode dégradé. Le delay loading permet de passer outre.

    Dans d'autres langages, on crée un module d'importation de la DLL qui va soit stubber les fonctions absentes (déclenchement d'exceptions / erreurs à l'exécution), soit les linker depuis la DLL si on arrive à les trouver. J'ai déjà fait souvent ça en Delphi, ça marche très bien, mais il faut hélas se palucher le code d'importation à la main et/ou utiliser un générateur de code.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    très exactement comme les librairies d'importation qui permettent d'importer des classes depuis une DLL (opération normalement impossible au vu du format des DLL Windows) grâce à un "hack" de la VMT des objets : la VMT est remplie via des GetProcAddress directement...
    Intéressant... J'aurais pensé que la VMT était exportée par la DLL en tant que variable globale. Mais c'est vrai que cela introduirait un niveau d'indirection lors de la création d'un objet depuis l'exe, pour récupérer l'adresse de la VMT dans la table d'importation...

    (COM contourne complètement le problème en ne créant les objets que dans la DLL).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    (COM contourne complètement le problème en ne créant les objets que dans la DLL).
    Oui, COM utilise une technologie radicalement différente... Et, accessoirement, bien plus compatible avec les autres langages / compilateurs.

    Dommage que la mise en œuvre soit nettement plus pénible qu'une "bête" classe C++, c'est vraiment le gros défaut de cette technologie je trouve.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Oui, COM utilise une technologie radicalement différente... Et, accessoirement, bien plus compatible avec les autres langages / compilateurs.
    Oui, c'est pour ça que j'en suis assez fan.

    Dommage que la mise en œuvre soit nettement plus pénible qu'une "bête" classe C++, c'est vraiment le gros défaut de cette technologie je trouve.
    J'ai fini par me faire ma propre variante d'ATL pour programmer des objets COM plus facilement. Ça reste assez simple tant qu'on n'en fait pas des composants COM (en clair, tant qu'on ne fait pas d'objets instantiables par CoCreateInstance)...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Ça reste assez simple tant qu'on n'en fait pas des composants COM (en clair, tant qu'on ne fait pas d'objets instantiables par CoCreateInstance)...
    C'est bien ça qui m'embête, justement : c'est plutôt le comportement "normal" qu'il me faudrait, la plupart du temps...

    Snif...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  13. #13
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Microsoft avait tenté de rendre l'utilisation d'ATL plus simple avec l'Attributed Programming, mais je trouve que ça apporte plus de confusion qu'autre chose.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Microsoft avait tenté de rendre l'utilisation d'ATL plus simple avec l'Attributed Programming, mais je trouve que ça apporte plus de confusion qu'autre chose.
    Je trouve aussi : c'est dommage, parce qu'à l'utilisation par contre, c'est pourtant très pratique.

    C'est vraiment à la création uniquement que ça pose des soucis... Rien d'insurmontable, bien sûr, mais ça demande à s'y mettre sérieusement et non pas "comme ça" pour réussir à bien appréhender tout le truc.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  15. #15
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Sur VC++, cette fonctionnalité sert à avoir un linkage statique de la DLL tout en tolérant l'absence de la DLL sur le système.
    Un autre intérêt qui a certainement perdu son... intérêt aujourd'hui est le fait que cela réduit le nombre de dlls à charger au lancement de l'application et permet donc de l'initialiser plus vite.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 12/02/2013, 01h08
  2. Fonction API
    Par margilb dans le forum C++Builder
    Réponses: 2
    Dernier message: 08/07/2002, 11h11
  3. Implémentation des fonctions mathématiques
    Par mat.M dans le forum Mathématiques
    Réponses: 9
    Dernier message: 17/06/2002, 16h19
  4. fonction printf
    Par ydeleage dans le forum C
    Réponses: 7
    Dernier message: 30/05/2002, 11h24
  5. FOnction api specifiant la position de la souris
    Par florent dans le forum C++Builder
    Réponses: 4
    Dernier message: 15/05/2002, 20h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo