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

Delphi Discussion :

L'inverse de GetProcAddress


Sujet :

Delphi

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut L'inverse de GetProcAddress
    Connaissant l'Adresse d'une Fonction dans une DLL, comment récupérer son nom (ou son ordinal) et le nom de la DLL à laquelle elle appartient?

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    On peut trouver les ordinaux et noms des fonctions dans la table d'export de la dll (voir ici). Dans la table d'import du programme (voir même lien), on a les noms des dll et adresses des fonctions.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 387
    Points : 2 999
    Points
    2 999

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    Merci pour vos réponses.
    Pourrais-je avoir un exemple (j’utilise Delphi7) de l’utilisation de la fonction SymFromAddr dans Dbghelp.dll.
    J'ai toujours une erreur :ERROR_ACCESS_DENIED.

  5. #5
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    As-tu encadré ton appel à SymFromAddr par un SymInitialize et un SymCleanup ?
    Si l'erreur persiste malgré l'initialisation, c'est pê un problème de droits, à explorer.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    Bonjour,
    Je n'avais pas encadré avec un SymInitialize et un SymCleanup.
    Maintenant ça marche un peu mieux.
    Mais SymFromAddr me renvoie l'erreur 126:ERROR_MOD_NOT_FOUND

    Dans SymInitialize que je mette le chemin de l'application ou de la DLL ou rien c'est pareil.
    Pourtant la dll est bien là, et la fonction existe , j' extrait son adresse avec GetProcAdress.
    J'ai encore du oublié quelque chose...

  7. #7
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    moi aussi ! avec le code suivant, j'obtiens une erreur 87 : paramètre incorrect...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    const
      DbgHelpDll = 'C:\windows\system32\dbghelp.dll';
      SYMFLAG_FUNCTION = $00000800; // 2048
     
    type
      TSYMBOL_INFO = packed record
        SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336
        TypeIndex: DWORD;
        Reserved_1, Reserved_2: uint64;
        Index: DWORD;
        Size: DWORD;
        ModBase: uint64;
        Flags: DWORD; // SYMFLAG_FUNCTION
        Value: uint64;
        Address: uint64;
        Registre: DWORD;
        Scope: DWORD;
        Tag: DWORD;
        NameLen: DWORD;
        MaxNameLen: DWORD; // 256
        Name: array[0..255] of AnsiChar;
      end;
     
    function SymInitialize(aHandle: HMODULE; aUserSearchPath: PAnsiChar;
                            aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll;
     
    function SymFromAddr(aHandle: HMODULE; aAdress: uint64;
                          var aDisplacement: uint64; var aSymbolInfo: TSYMBOL_INFO): Boolean; stdcall; external DbgHelpDll;
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Hmod: HMODULE;
      P: Pointer;
      i, Deplacement: uint64;
      SymbolInfo: TSYMBOL_INFO;
      Result: AnsiString;
    begin
      Hmod:=LoadLibrary(DbgHelpDll);
      if Hmod=0 then
      begin
        ShowMessage('librairie pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      P:=nil;
      P:=GetProcAddress(Hmod, 'SymFromName'); // pour charger la 1ère fonction
      if not Assigned(P) then
      begin
        ShowMessage('fonction pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      if not SymInitialize(Hmod, nil, False) then
      begin
        ShowMessage('symboles pas initialisés');
        FreeLibrary(Hmod);
        Exit;
      end;
      i:=SizeOf(TSymbol_Info);
      FillChar(SymbolInfo, i, 0);
      SymbolInfo.SizeOfStruct:=i; // 336 si packed   
      SymbolInfo.MaxNameLen:=256;
      Deplacement:=0;
      if SymFromAddr(Hmod, UInt64(P), Deplacement, SymbolInfo) then
      begin
        if SymbolInfo.Flags and SYMFLAG_FUNCTION <> SYMFLAG_FUNCTION then
        begin
          ShowMessage('le symbole retourné n''est pas une fonction');
          FreeLibrary(Hmod);
          Exit;
        end;
        SetLength(Result, SymbolInfo.NameLen);
        for i:=1 to SymbolInfo.NameLen
        do Result[i]:=SymbolInfo.Name[i];
        ShowMessage(Result);
      end
      else begin
        i:=GetLastError;
        ShowMessage('infos pas retournées ; erreur '+IntToStr(i));
      end;
      if not SymCleanup(Hmod) then
        ShowMessage('symboles pas nettoyés');
      FreeLibrary(Hmod);
    end;
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    Comme ceci ça marche

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     const
      DbgHelpDll = 'C:\windows\system32\dbghelp.dll';
      SYMFLAG_FUNCTION = $00000800 or $200; // fonction ou export table
     
    type
      TSYMBOL_INFO =  record
        SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336
        TypeIndex: DWORD;
        Reserved_1, Reserved_2: uint64;
        Index: DWORD;
        Size: DWORD;
        ModBase: int64;
        Flags: DWORD; // SYMFLAG_FUNCTION
        Value: Int64;
        Address: int64;
        Registre: DWORD;
        Scope: DWORD;
        Tag: DWORD;
        NameLen: DWORD;
        MaxNameLen: DWORD; //256
        Name: array[0..255] of AnsiChar;
      end;
     
    function SymInitialize(aHandle: HMODULE; aUserSearchPath: PAnsiChar;
                            aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll;
     
    function SymFromAddr(aHandle: HMODULE; aAdress:int64;
                          aDisplacement:DWORD;
                          aSymbolInfo: pointer): Boolean; stdcall; external DbgHelpDll;
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
     var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Hmod,Hprocessus: HMODULE;
      P: Pointer;
      i:cardinal;
      Deplacement:dword;
      SymbolInfo: TSYMBOL_INFO;
      Result: string;
    begin
      Hprocessus:=getcurrentprocess;
      Hmod:=LoadLibrary('kernel32.dll'); //une dll quelconque
      if Hmod=0 then
      begin
        ShowMessage('librairie pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      P:=nil;
      P:=GetProcAddress(Hmod, 'AddAtomA');//une fonction quelconque,l'adresse peut être supérieur jusqu'à la prochaine fonction
     
      if not Assigned(P) then
      begin
        ShowMessage('fonction pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      if not SymInitialize(Hprocessus, nil, true) then
      begin
        ShowMessage('symboles pas initialisés');
        FreeLibrary(Hmod);
        Exit;
      end;
      i:=SizeOf(TSymbol_Info);
      zeromemory(@SymbolInfo,i);
      SymbolInfo.SizeOfStruct:=i; // 336 si packed
      SymbolInfo.MaxNameLen:=255;
      Deplacement:=0;
      if SymFromAddr(Hprocessus, int64(p), Deplacement, @SymbolInfo) then  // mettre le handle du processus
      begin
        if (SymbolInfo.Flags and SYMFLAG_FUNCTION) = 0 then
        begin
          ShowMessage('le symbole retourné n''est pas une fonction');
          FreeLibrary(Hmod);
          Exit;
        end;
        SetLength(Result, SymbolInfo.NameLen);
        for i:=0 to SymbolInfo.NameLen
        do Result:=SymbolInfo.Name;
        ShowMessage(Result);
      end
      else begin
        i:=GetLastError;
        ShowMessage('infos pas retournées ; erreur '+IntToStr(i));
      end;
      if not SymCleanup(Hprocessus) then
        ShowMessage('symboles pas nettoyés');
      FreeLibrary(Hmod);
    end;

  9. #9
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Mince ! Je pensais qu'en passant le paramètre record en var on passait son adresse, soit l'équivalent d'un pointeur en C... Mauvaise traduction...
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  10. #10
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    c'est surtout que tu ne prenez pas le bon handle de process aussi
    tu passe le handle du loadlibrary alors qu'il faut le handle du processus courant (application)
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  11. #11
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 387
    Points : 2 999
    Points
    2 999
    Par défaut
    Ce serait bien d'ajouter le résultat final à FAQ.

    Sergio ? ton avis ?

  12. #12
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Bonjour,

    comme le code m’intéresse aussi, je l'ai testé (le dernier posté par "angel_f") et j'ai toujours "infos pas retournées ; erreur 87" !!!
    une idée du problème ?
    testé sous D2009 & Win7

    Cordialement,
    @+

  13. #13
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 387
    Points : 2 999
    Points
    2 999
    Par défaut
    là, j'ai pas trop le temps mais je ferai un essai ce soir

    Déjà, si le code a été testé correct sous Delphi 7, vu que tu utilises Delphi 2009 unicode, il y a peut-être à voir de ce côté là.

  14. #14
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    là, j'ai pas trop le temps mais je ferai un essai ce soir

    Déjà, si le code a été testé correct sous Delphi 7, vu que tu utilises Delphi 2009 unicode, il y a peut-être à voir de ce côté là.
    j'y ai pensé à l'UNICODE mais ça ne change rien
    déjà de base les fonctions appelées sont en Ansi et le record aussi donc ça devrait passer mais non

    j'ai changé pour appeler les fonctions UNICODE "W" et modifié le record en conséquence ... toujours erreur 87

    du coup j'ai testé le code original tel quel avec D7 et j'ai le même problème ... erreur 87
    j'ai également testé en mode Administrateur au cas ou ... idem

    du coup je ne pense pas que ce soit lié à la version de Delphi (UNICODE ou non)

    Mais il y a peut être un truc qui m'échappe

    Cordialement,
    @+

  15. #15
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    Erreur localisée :
    Dans mon projet j’utilise la version 5.1 de dbghelp.dll.
    Sous win 7 c’est la version 6.1 qui entraîne une erreur.
    2 solutions :
    - Mettre la version 5.1 dans le projet, marche sous win7
    - Trouver la différence entre 5.1 et 6.1 que je ne connais pas

  16. #16
    Futur Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Décembre 2016
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Décembre 2016
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    Problème résolu :
    Pour Dbghelp.dll version 6.1
    Dans SYMBOL_INFO. SizeOfStruct mettre la valeur $58 ne pas tenir compte de la longueur du nom.

  17. #17
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par angel_f Voir le message
    Problème résolu :
    Pour Dbghelp.dll version 6.1
    Dans SYMBOL_INFO. SizeOfStruct mettre la valeur $58 ne pas tenir compte de la longueur du nom.
    Effectivement ça fonctionne parfaitement
    Merci.

    Fixer ainsi arbitrairement la taille du record ne me plait pas trop.
    Pour donner une certaine cohérence au code (quand on essaye le lire) je propose de l'écrire comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      SymbolInfo.MaxNameLen := 256;
      SymbolInfo.SizeOfStruct := I - SymbolInfo.MaxNameLen; // 88
    ce qui me semble plus claire et surtout explique la taille de 88 ($58)

    EDIT:
    Après avoir testé la version UNICODE et
    dans un souci de compatibilité entre les deux je propose une dernière modification du code comme ceci:
    Il fonctionne aussi bien sous D7(ansi) que sous D2009 (UNICODE) sans changer une virgule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    unit Unit5;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
     
    type
      TForm5 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    const
      DbgHelpDll   = 'C:\windows\system32\dbghelp.dll';
      SYMFLAG_FUNCTION = $00000800 or $200; // fonction ou export table
     
    type
      TSYMBOL_INFO = record
        SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336
        TypeIndex: DWORD;
        Reserved_1, Reserved_2: uint64;
        Index: DWORD;
        Size: DWORD;
        ModBase: int64;
        Flags: DWORD; // SYMFLAG_FUNCTION
        Value: Int64;
        Address: int64;
        Registre: DWORD;
        Scope: DWORD;
        Tag: DWORD;
        NameLen: DWORD;
        MaxNameLen: DWORD; //256
        Name: array[0..255] of Char;   // AnsiChar
      end;
     
    function SymInitialize(aHandle: HMODULE; aUserSearchPath: PChar;
      aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymInitializeW'
    {$ELSE}
      name 'SymInitialize'
    {$ENDIF};
     
    function SymFromAddr(aHandle: HMODULE;
      aAdress: int64;
      aDisplacement: DWORD;
      aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymFromAddrW'
    {$ELSE}
      name 'SymFromAddr'
    {$ENDIF};
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
    var
      Form5        : TForm5;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm5.Button1Click(Sender: TObject);
    var
      Hmod, Hprocessus: HMODULE;
      P            : Pointer;
      i            : cardinal;
      Deplacement  : dword;
      SymbolInfo   : TSYMBOL_INFO;
      Result       : string;
    begin
      Hprocessus := getcurrentprocess;
      Hmod := LoadLibrary('kernel32.dll'); //une dll quelconque
      if Hmod = 0 then
      begin
        ShowMessage('librairie pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      //P := nil;
      P := GetProcAddress(Hmod, 'AddAtomA');
        //une fonction quelconque,l'adresse peut être supérieur jusqu'à la prochaine fonction
     
      if not Assigned(P) then
      begin
        ShowMessage('fonction pas chargée');
        FreeLibrary(Hmod);
        Exit;
      end;
      if not SymInitialize(Hprocessus, nil, true) then
      begin
        ShowMessage('symboles pas initialisés');
        FreeLibrary(Hmod);
        Exit;
      end;
      i := SizeOf(TSymbol_Info);
      zeromemory(@SymbolInfo, i);
      SymbolInfo.MaxNameLen := 256;
      SymbolInfo.SizeOfStruct :=  I - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]); // 88
      Deplacement := 0;
      if SymFromAddr(Hprocessus, int64(p), Deplacement, @SymbolInfo) then
        // mettre le handle du processus
      begin
        if (SymbolInfo.Flags and SYMFLAG_FUNCTION) = 0 then
        begin
          ShowMessage('le symbole retourné n''est pas une fonction');
          FreeLibrary(Hmod);
          Exit;
        end;
        {SetLength(Result, SymbolInfo.NameLen);
        for i := 0 to SymbolInfo.NameLen do} Result := SymbolInfo.Name;
        ShowMessage(Result);
      end
      else begin
        i := GetLastError;
        ShowMessage('infos pas retournées ; erreur ' + IntToStr(i));
      end;
      if not SymCleanup(Hprocessus) then
        ShowMessage('symboles pas nettoyés');
      FreeLibrary(Hmod);
    end;
    end.
    je pense que cette fois c'est la dernière

    qu'en pensez-vous ?
    Cordialement,
    @+

  18. #18
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 387
    Points : 2 999
    Points
    2 999
    Par défaut
    qu'en pensez-vous ?
    Je testerai ce w-e, pas le temps aujourd'hui.

    Mais j'en pense qu'il faudrait juste extraire ça dans une unité séparée réutilisable et l'ajouter (je me répète, désolé) à la FAQ

  19. #19
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je voulais revisiter le code de Cirec sous forme d'une fonction autonome, mais je ne parviens pas à inclure les déclarations de fonctions externes dedans : le compilateur n'y reconnaît pas la directive external.

    Du coup, je propose ceci, qui n'est pas self-contained, que je n'ai testé qu'avec Berlin 10.1 sous Win7, et dans lequel j'ai ôté tout le code de gestion d'erreurs, surtout utile lors du débogage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    const
      DbgHelpDll = 'C:\windows\system32\dbghelp.dll';
     
    function SymInitialize(aHandle: HMODULE;
     aUserSearchPath: PChar;
     aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymInitializeW'
    {$ELSE}
      name 'SymInitialize'
    {$ENDIF};
     
    function SymFromAddr(aHandle: HMODULE;
     aAdress: uint64;
     var aDisplacement: Cardinal;
     aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymFromAddrW'
    {$ELSE}
      name 'SymFromAddr'
    {$ENDIF};
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
    // retourne le nom d'une fonction d'une bibliothèque à partir de son adresse.
    function GetDllFunctionNameFromAddress(aAddress: Pointer): String;
    const
      SYMFLAG_FUNCTION = $00000800 or $00000200; // fonction ou export table
      MaxSymbolNameLen = 256;
     
    type
      TSYMBOL_INFO = record
        SizeOfStruct: Cardinal;
        TypeIndex: Cardinal;
        Reserved_1, Reserved_2: uint64;
        Index: Cardinal;
        Size: Cardinal;
        ModBase: uint64;
        Flags: Cardinal; // SYMFLAG_FUNCTION
        Value: uint64;
        Address: uint64;
        Registre: Cardinal;
        Scope: Cardinal;
        Tag: Cardinal;
        NameLen: Cardinal;
        MaxNameLen: Cardinal; // MaxSymbolNameLen (modifiable)
        Name: array[0..MaxSymbolNameLen-1] of Char; // pas à inclure dans TSYMBOL_INFO.SizeOfStruct
      end;
     
    var
      ProcessHandle: HMODULE;
      i, Deplacement: Cardinal;
      SymbolInfo: TSYMBOL_INFO;
     
    begin
      Result := EmptyStr;
      ProcessHandle := GetCurrentProcess;
      // initialisation de la table des symboles
      if not SymInitialize(ProcessHandle, nil, True) then Exit;
      // initialisation de la structure pour le retour des infos
      i := SizeOf(TSymbol_Info);
      ZeroMemory(@SymbolInfo, i);
      SymbolInfo.MaxNameLen := MaxSymbolNameLen;
      SymbolInfo.SizeOfStruct :=  i - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]);
      Deplacement := 0;
      // informations sur l'adresse demandée
      if SymFromAddr(ProcessHandle, int64(aAddress), Deplacement, @SymbolInfo) then
      begin
        if (SymbolInfo.Flags or SYMFLAG_FUNCTION) = SYMFLAG_FUNCTION  // filtre les fonctions
        then Result := SymbolInfo.Name;
      end;
      // libération de la table des symboles
      SymCleanup(ProcessHandle);
    end;
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  20. #20
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Bonjour,
    Je voulais revisiter le code de Cirec sous forme d'une fonction autonome, mais je ne parviens pas à inclure les déclarations de fonctions externes dedans : le compilateur n'y reconnaît pas la directive external.

    Du coup, je propose ceci, qui n'est pas self-contained, que je n'ai testé qu'avec Berlin 10.1 sous Win7, et dans lequel j'ai ôté tout le code de gestion d'erreurs, surtout utile lors du débogage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    const
      DbgHelpDll = 'C:\windows\system32\dbghelp.dll';
     
    function SymInitialize(aHandle: HMODULE;
     aUserSearchPath: PChar;
     aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymInitializeW'
    {$ELSE}
      name 'SymInitialize'
    {$ENDIF};
     
    function SymFromAddr(aHandle: HMODULE;
     aAdress: uint64;
     var aDisplacement: Cardinal;
     aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymFromAddrW'
    {$ELSE}
      name 'SymFromAddr'
    {$ENDIF};
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
    // retourne le nom d'une fonction d'une bibliothèque à partir de son adresse.
    function GetDllFunctionNameFromAddress(aAddress: Pointer): String;
    const
      SYMFLAG_FUNCTION = $00000800 or $00000200; // fonction ou export table
      MaxSymbolNameLen = 256;
     
    type
      TSYMBOL_INFO = record
        SizeOfStruct: Cardinal;
        TypeIndex: Cardinal;
        Reserved_1, Reserved_2: uint64;
        Index: Cardinal;
        Size: Cardinal;
        ModBase: uint64;
        Flags: Cardinal; // SYMFLAG_FUNCTION
        Value: uint64;
        Address: uint64;
        Registre: Cardinal;
        Scope: Cardinal;
        Tag: Cardinal;
        NameLen: Cardinal;
        MaxNameLen: Cardinal; // MaxSymbolNameLen (modifiable)
        Name: array[0..MaxSymbolNameLen-1] of Char; // pas à inclure dans TSYMBOL_INFO.SizeOfStruct
      end;
     
    var
      ProcessHandle: HMODULE;
      i, Deplacement: Cardinal;
      SymbolInfo: TSYMBOL_INFO;
     
    begin
      Result := EmptyStr;
      ProcessHandle := GetCurrentProcess;
      // initialisation de la table des symboles
      if not SymInitialize(ProcessHandle, nil, True) then Exit;
      // initialisation de la structure pour le retour des infos
      i := SizeOf(TSymbol_Info);
      ZeroMemory(@SymbolInfo, i);
      SymbolInfo.MaxNameLen := MaxSymbolNameLen;
      SymbolInfo.SizeOfStruct :=  i - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]);
      Deplacement := 0;
      // informations sur l'adresse demandée
      if SymFromAddr(ProcessHandle, int64(aAddress), Deplacement, @SymbolInfo) then
      begin
        if (SymbolInfo.Flags or SYMFLAG_FUNCTION) = SYMFLAG_FUNCTION  // filtre les fonctions
        then Result := SymbolInfo.Name;
      end;
      // libération de la table des symboles
      SymCleanup(ProcessHandle);
    end;
    je ne comprends pas bien où se situe ton problème ?

    j'ai repris ton code tel quel et je l'ai mis dans une unité et voilà:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    unit UGetProcName;
     
    interface
    function GetDllFunctionNameFromAddress(aAddress: Pointer): String;
     
    implementation
    uses Windows, SysUtils;
    const
      DbgHelpDll = 'dbghelp.dll';
     
    function SymInitialize(aHandle: HMODULE;
     aUserSearchPath: PChar;
     aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymInitializeW'
    {$ELSE}
      name 'SymInitialize'
    {$ENDIF};
     
    function SymFromAddr(aHandle: HMODULE;
     aAdress: uint64;
     var aDisplacement: Cardinal;
     aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll
    {$IFDEF UNICODE}
      name 'SymFromAddrW'
    {$ELSE}
      name 'SymFromAddr'
    {$ENDIF};
     
    function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll;
     
    // retourne le nom d'une fonction d'une bibliothèque à partir de son adresse.
    function GetDllFunctionNameFromAddress(aAddress: Pointer): String;
    const
      SYMFLAG_FUNCTION = $00000800 or $00000200; // fonction ou export table
      MaxSymbolNameLen = 256;
     
    type
      TSYMBOL_INFO = record
        SizeOfStruct: Cardinal;
        TypeIndex: Cardinal;
        Reserved_1, Reserved_2: uint64;
        Index: Cardinal;
        Size: Cardinal;
        ModBase: uint64;
        Flags: Cardinal; // SYMFLAG_FUNCTION
        Value: uint64;
        Address: uint64;
        Registre: Cardinal;
        Scope: Cardinal;
        Tag: Cardinal;
        NameLen: Cardinal;
        MaxNameLen: Cardinal; // MaxSymbolNameLen (modifiable)
        Name: array[0..MaxSymbolNameLen-1] of Char; // pas à inclure dans TSYMBOL_INFO.SizeOfStruct
      end;
     
    var
      ProcessHandle: HMODULE;
      i, Deplacement: Cardinal;
      SymbolInfo: TSYMBOL_INFO;
     
    begin
      Result := EmptyStr;
      ProcessHandle := GetCurrentProcess;
      // initialisation de la table des symboles
      if not SymInitialize(ProcessHandle, nil, True) then Exit;
      // initialisation de la structure pour le retour des infos
      i := SizeOf(TSymbol_Info);
      ZeroMemory(@SymbolInfo, i);
      SymbolInfo.MaxNameLen := MaxSymbolNameLen;
      SymbolInfo.SizeOfStruct :=  i - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]);
      Deplacement := 0;
      // informations sur l'adresse demandée
      if SymFromAddr(ProcessHandle, int64(aAddress), Deplacement, @SymbolInfo) then
      begin
        if (SymbolInfo.Flags or SYMFLAG_FUNCTION) = SYMFLAG_FUNCTION  // filtre les fonctions
        then Result := SymbolInfo.Name;
      end;
      // libération de la table des symboles
      SymCleanup(ProcessHandle);
    end;
    end.
    et ça fonctionne

    Cordialement,
    @+

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. inverser l'écran
    Par relax_06 dans le forum C++Builder
    Réponses: 2
    Dernier message: 13/03/2004, 12h20
  2. inverser la lecture d'une requète
    Par nilaco dans le forum Requêtes
    Réponses: 5
    Dernier message: 10/08/2003, 12h16
  3. [VB6] [Graphisme] Inversion dans picturebox
    Par tomnie dans le forum VB 6 et antérieur
    Réponses: 23
    Dernier message: 16/04/2003, 15h05
  4. Inverser une chaîne de caractères
    Par DBBB dans le forum Assembleur
    Réponses: 2
    Dernier message: 30/03/2003, 11h09
  5. [VB6]fonction inverse de Hex (nombres hexadécimaux)
    Par Guigui_ dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 08/10/2002, 19h31

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