[c/c++/dll]Pourquoi ce programme provoque une erreur (windows)?

Pourquoi ce programme provoque une erreur (windows)? [c/c++/dll] - C++ - Programmation

Marsh Posté le 18-04-2002 à 20:31:59    

Salut
 
Quelqu'un pourrait m'expliquer pourquoi ce programme (très inspiré de http://www.codeguru.com/system/killer.html) provoque une erreur (et est fermé par windows)?
 
Le problème viendrai de la ligne 54 (le if), si elle est mise en commentaire y a plus le problème. La ligne 56 quant a elle ferait planter le programme plus rapidement. (dépassement? mais d'où viendrait il?)
 
(Ce programme utilise la dll psapi, donc seul les pocesseurs de NT, 2k et xp peuvent l'essayer.)
 
#include <stdio.h>
#include <windows.h>
#include <iostream.h>
 
int main(int argc, char *argv[])
{ CHAR   szProcessName[MAX_PATH] = _T("unknown" );  HMODULE hMod;
 
HINSTANCE hModPSAPI ;
typedef bool (*PEnumProcesses)(DWORD* , UINT, DWORD *);
typedef bool (*PEnumProcessesModules)( HANDLE, HMODULE*, DWORD, LPDWORD );
typedef DWORD (WINAPI *PGetModuleBaseName)( HANDLE, HMODULE, LPTSTR, UINT );
 
hModPSAPI  = LoadLibrary("psapi.dll" );
PEnumProcesses EnumProcesses;
EnumProcesses = (PEnumProcesses) GetProcAddress(hModPSAPI ,"EnumProcesses" );
PEnumProcessesModules EnumProcessesModules;
EnumProcessesModules = (PEnumProcessesModules) GetProcAddress(hModPSAPI,"EnumProcessModules" );
 
#ifdef UNICODE
 PGetModuleBaseName GetModuleBaseName =  
 (PGetModuleBaseName)GetProcAddress( hModPSAPI,
                                     "GetModuleBaseNameW" );
#else
 PGetModuleBaseName GetModuleBaseName =  
 (PGetModuleBaseName)GetProcAddress( hModPSAPI,
                                     "GetModuleBaseNameA" );
#endif
 
 
if ( !EnumProcesses) {printf("pb" ); getchar(); return false;}
 
DWORD lpidProcess[100];  // array of process identifiers
//DWORD cb=100;            // size of array
DWORD cbNeeded;      // number of bytes returned
 
 
if(EnumProcesses(lpidProcess,sizeof(lpidProcess),&cbNeeded))
  { //printf("nb octets:%d\n",cbNeeded);
   int nb_proc=cbNeeded/sizeof(DWORD);
   printf("nb de processus: %d\n",nb_proc);
   //printf("liste des processus:\n" );
   for(int i=0;i<nb_proc;i++)
    {
    printf("num: %d PID:%d\n",i,lpidProcess[i]);//}
     HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lpidProcess[i] );
     cout<<hProcess<<"\n";
     if ( hProcess==NULL ) {printf("echec! erreur: %d\n",GetLastError());} else
      { //cout<<hProcess<<"\n";
        //printf("%d\n",lpidProcess[i]);
      getchar();
 

        if ( EnumProcessesModules( hProcess, &hMod, (DWORD) sizeof(hMod), &cbNeeded) )    // ligne 54
        {
           GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) );    //56

           
           cout<<szProcessName<<"\n";
           
        }
      }
 
     CloseHandle( hProcess );
    }
 
 
   } else printf("echec! erreur: %d",GetLastError());
  getchar();
  return 0;
}

 

[jfdsdjhfuetppo]--Message édité par nico23--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 18-04-2002 à 20:31:59   

Reply

Marsh Posté le 19-04-2002 à 00:07:04    

Je suis pas sûr du tout mais essaye :
if(EnumProcesses(&lpidProcess,sizeof(lpidProcess),&cbNeeded))

Reply

Marsh Posté le 19-04-2002 à 13:30:49    

Messire_Le_Geux a écrit a écrit :

Je suis pas sûr du tout mais essaye :
if(EnumProcesses(&lpidProcess,sizeof(lpidProcess),&cbNeeded))  




le problème ne vient pas de cette ligne (elle est bonne car je récupère les PID des Processus) mais de EnumProcessModules.
 
 [:dirakocha]
 
edit: lpidProcess est un tableau, donc son adresse est bien lpidProcess (et sa valeur lpidProcess[i] )
et j'ai vérifié sur http://www.codeguru.com/system/killer.html

 

[jfdsdjhfuetppo]--Message édité par nico23--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 19-04-2002 à 17:34:52    

[:ruisseau%20de%20larmes]  [:dirakocha]

Reply

Marsh Posté le 19-04-2002 à 17:45:03    

aucune idée, jamais bossé avec ça. en attendant, tu peux essayer plusieurs trucs :
 
* aligner ton bloc de mem sur 4 octets
* passer à la fonction un trèèès gros tableau
* passer à la fonction le nombre d'entrées du tableau, et pas sa taille en bytes
 
oui, le dernier point contredit la doc. mais la doc crosoft, sur les trucs pointus, j'ai essayé et j'ai eu beaucoup de problèmes. teste voir.
 
si tu ne veux qu'énumérer les process, tu peux utiliser la librairie toolhelp (qui énumère les process, threads, dlls) : http://msdn.microsoft.com/library/ [...] Module.asp

Reply

Marsh Posté le 19-04-2002 à 17:46:36    

(et toolhelp marche aussi sur win9x).

Reply

Marsh Posté le 19-04-2002 à 18:21:35    

youdontcare a écrit a écrit :

 
* aligner ton bloc de mem sur 4 octets
 




 :??:  je comprend pas ce que tu veux dire?
 
merci pour ces infos, je vais essayer (j'essayerai toolhelp un peu plus tard)

 

[jfdsdjhfuetppo]--Message édité par nico23--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 19-04-2002 à 18:27:23    

nico23 a écrit a écrit :

 :??:  je comprend pas ce que tu veux dire?


c'est juste un des trucs qui m'est venu à l'esprit, y'a de fortes chances que ça n'ait rien à voir, mais on sait jamais.
 
aligner =
 
char* ptr = new .....
ptr = 0x78787f
 
aligné sur 4 octets, l'adresse est un multiple de 4. (la taille d'un pid).  
 
et tu obtiens quelle taille dans cbNeeded ?

Reply

Marsh Posté le 19-04-2002 à 18:50:18    

youdontcare a écrit a écrit :

 
* passer à la fonction un trèèès gros tableau
* passer à la fonction le nombre d'entrées du tableau, et pas sa taille en bytes
 




Je viens de regarder le code mais il n'y a pas de tableau. :(  
HMODULE hMod;
 
        if ( EnumProcessesModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )    // ligne 54
        {
           GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) );    //56

Reply

Marsh Posté le 19-04-2002 à 18:56:57    

plus haut j'ai écrit a écrit :

et tu obtiens quelle taille dans cbNeeded ?


et si tu lui passais un (gros) tableau à la fonction ?

Reply

Marsh Posté le 19-04-2002 à 18:56:57   

Reply

Marsh Posté le 19-04-2002 à 18:59:10    

youdontcare a écrit a écrit :

c'est juste un des trucs qui m'est venu à l'esprit, y'a de fortes chances que ça n'ait rien à voir, mais on sait jamais.
 
aligner =
 
char* ptr = new .....
ptr = 0x78787f
 
aligné sur 4 octets, l'adresse est un multiple de 4. (la taille d'un pid).  
 
et tu obtiens quelle taille dans cbNeeded ?  




la taille dépend du nom récupérer si c'est InternetExplorer.exe cbNeeded =264 (j'en ai un autre à 104 mais ca plante lorsque je veux récupérer le nom, si je mets en commentaire le getmodulebasename je vais un peut plus loin avant un autre plantage du cette fois à enumprocessmodules)

Reply

Marsh Posté le 19-04-2002 à 19:10:59    

youdontcare a écrit a écrit :

et si tu lui passais un (gros) tableau à la fonction ?  




 
Ca change rien.

Reply

Marsh Posté le 19-04-2002 à 19:13:52    

Quant on fait int * ptr=new int[10];
il faut faire delete [10] ptr; ou delete ptr; ?
D'après ma doc il faut faire la 1ère solution mais mon compilateur n'en veut pas.

Reply

Marsh Posté le 19-04-2002 à 19:19:21    

trois choses :
 
* j'ai lu ton code plus en détail, c'est infâme. INDENTE et SOIS CONSISTENT. (tu es en partie responsable de mon mal de crâne :lol:)
 
* CHAR   szProcessName[MAX_PATH] = _T("unknown" );  
 
vire cette atrocité. je n'ai aucune idée du comportement de la chose. char name[...]; ok. ensuite pour copier une string dedans, strcpy(). un char* name = "string" alloue un tableau de la taille de la string en question.
 
* passe un tableau à EnumProcessesModules() :
 
HMODULE modules[1024];
 
if (EnumProcessesModules(..., modules, sizeof(modules), ...)

Reply

Marsh Posté le 19-04-2002 à 19:19:50    

nico23 a écrit a écrit :

Quant on fait int * ptr=new int[10];
il faut faire delete [10] ptr; ou delete ptr; ?
D'après ma doc il faut faire la 1ère solution mais mon compilateur n'en veut pas.


delete [] ptr.

Reply

Marsh Posté le 19-04-2002 à 23:34:29    

J'ai fait le programme avec la librairie toolhelp et la j'ai pas de problème. Je me demande d'où vient le problème popur l'autre programme.

Reply

Marsh Posté le 20-04-2002 à 11:06:45    

nico23 a écrit a écrit :

J'ai fait le programme avec la librairie toolhelp et la j'ai pas de problème.


:) cool.
 

nico23 a écrit a écrit :

Je me demande d'où vient le problème popur l'autre programme.


me too. mais comme je n'ai ni 2000 ni xp, je ne peux pas tester.

Reply

Marsh Posté le 20-04-2002 à 17:30:46    

Maintenant pour m'éviter de tous redéclaré a chaque fois (si j'ai besoin de réutiliser ces fonctions), je voudrais savoir comment je pourrais déclarer des librairies (avec le fichier header ...) pour utiliser ces fonctions de dll. (j'ai pas les headers car j'utilise dev-c++)
 
Pour éviter de faire ca à chaque fois:
typedef HANDLE (WINAPI *PCreateToolhelp32Snapshot) (DWORD , DWORD );
HINSTANCE hModPSAPI  = LoadLibrary("KERNEL32.dll" );
PCreateToolhelp32Snapshot CreateToolhelp32Snapshot;
CreateToolhelp32Snapshot = (PCreateToolhelp32Snapshot) GetProcAddress(hModPSAPI ,"CreateToolhelp32Snapshot" );

Reply

Marsh Posté le 20-04-2002 à 17:34:47    

j'ai écrit a écrit :

J'ai fait le programme avec la librairie toolhelp et la j'ai pas de problème. Je me demande d'où vient le problème popur l'autre programme.  




 
enfin si un petit: dans les msdn ils disent (si j'ai bien traduit) qu'il faut utiliser la fonction CloseToolhelp32Snapshot et pas closehandle sinon ca fait une erreur. Or j'ai le contraire, plantage si j'utilise CloseToolhelp32Snapshot et pas de plantage pour closehandle (d'ailleurs le closehandle retourne true donc il a bien fonctionné): bizzare!
 
edit:
PS:
[citation]
trois choses :  
 
* j'ai lu ton code plus en détail, c'est infâme. INDENTE et SOIS CONSISTENT. (tu es en partie responsable de mon mal de crâne :lol:)  
 
* CHAR   szProcessName[MAX_PATH] = _T("unknown" );    
 
vire cette atrocité. je n'ai aucune idée du comportement de la chose. char name[...]; ok. ensuite pour copier une string dedans, strcpy(). un char* name = "string" alloue un tableau de la taille de la string en question.  
 
* passe un tableau à EnumProcessesModules() :  
 
HMODULE modules[1024];  
 
if (EnumProcessesModules(..., modules, sizeof(modules), ...) [/citation]
Le code n'est pas de moi à 100% (seulement environ 95%  :D )
exemple pris sur: http://www.codeguru.com/system/killer.html

 

[jfdsdjhfuetppo]--Message édité par nico23--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 21-04-2002 à 17:14:32    

>> Maintenant pour m'éviter de tous redéclaré a chaque fois
 
dans l'exemple, il déclare pour pouvoir charger la dll dynamiquement -> le code marchera sur tout windows, en cas d'erreur (si pas nt, la fonction n'est pas dispo), il peut afficher son message d'erreur explicatif. sinon windows te sort un charabia.
 
donc pour éviter de tout redéclarer, tu inclus le .h, tu appelles la fonction, et s'il faut une librairie, tu linkes avec elle (project settings > link).
 
>> problème avec CloseHandle()
 
houla, j'en sais rien, réinstalle windows ? :D
 
>> Le code n'est pas de moi à 100% (seulement environ 95%    )  
 
ce qui n'empêche qu'il est infâme. tu es sur un forum, la moindre des politesses est de présenter un code lisible et de se relire.

Reply

Marsh Posté le 21-04-2002 à 22:44:54    

youdontcare a écrit a écrit :

 
dans l'exemple, il déclare pour pouvoir charger la dll dynamiquement -> le code marchera sur tout windows, en cas d'erreur (si pas nt, la fonction n'est pas dispo), il peut afficher son message d'erreur explicatif. sinon windows te sort un charabia.
 
donc pour éviter de tout redéclarer, tu inclus le .h, tu appelles la fonction, et s'il faut une librairie, tu linkes avec elle (project settings > link).
 




Tu as peut-être pas fait attention, mais j'ai dit que je n'avait pas le .h (j'utilises dev-c++) donc je souhaite le crée avec la librairie.
Mais je trouve pas ca terrible de faire un truc du genre:
 
HANDLE CreateToolhelp32Snapshot (DWORD SNAP, DWORD ID)
{
typedef HANDLE (WINAPI *PCreateToolhelp32Snapshot) (DWORD , DWORD );
hModPSAPI  = LoadLibrary("KERNEL32.dll" );
PCreateToolhelp32Snapshot sCreateToolhelp32Snapshot;
sCreateToolhelp32Snapshot = (PCreateToolhelp32Snapshot) GetProcAddress(hModPSAPI ,"CreateToolhelp32Snapshot" );
return sCreateToolhelp32Snapshot(SNAP,ID);
}
 
Donc existerait-il un autre moyen pour déclaré les fonctions d'une dll (pour eviter de redefinir la fonction comme ci dessus)?

Reply

Marsh Posté le 21-04-2002 à 22:54:22    

nico23 a écrit a écrit :

Donc existerait-il un autre moyen pour déclaré les fonctions d'une dll (pour eviter de redefinir la fonction comme ci dessus)?


non. mais tu peux toujours écrire une macro.
 
si tu downloades la platform sdk sur msdn.microsoft.com, tu devrais avoir les headers.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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