Newsgroup: it.comp.lang.delphi
Titolo: hook

Salve a tutti. Sono un novizio della programmazione in Delphi (sono uscito da
poco dalla fase "Hello World")e ultimamente mi sono cimentato nella scrittura
di un Hook di sistema che, ovviamente, non funziona.
Riporto il sorgente della DLL che contiene l'hook:
uses
  SysUtils,
  Windows,
  Dialogs,
  Classes;
var
   LogFile: String; //Nome e percorso del file di log
   HookAdr: HHOOK; //Handle dell'hook
{$R *.RES}
function MonLog(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
stdcall;
{
 Questa funzione si inserisce nella catena degli Hook di sistema di Windows e
monitorizza
 tutte le finestre che vengono create e distrutte riportandole in un file di
log insieme
 ad altre informazioni sul nome della finestra, data ed ora di creazione o
distruzione e
 file eseguibile cui appartiene la finestra.
}
var
   Str: String;
   Title, Namef: array[0..255] of Char;
   nFile: Textfile;
   ProcId, ProcHnd: THandle;
begin
     if nCode = HSHELL_WINDOWCREATED then
     begin
          AssignFile(nFile,LogFile);
          Append(nFile);
          GetWindowText(wParam,Title,256);
          ProcId := GetWindowThreadProcessId(wParam,nil);
          ProcHnd := OpenProcess(PROCESS_ALL_ACCESS,False,ProcId);
          GetModuleFileName(ProcHnd,Namef,256);
          CloseHandle(ProcHnd);
          Str := 'Attivato    "' + Title + '" in data ' + DateTimeToStr(Now) +
' da: [' + Namef + '].';
          Writeln(nFile,Str);
          Flush(nFile);
          CloseFile(nFile);
     end;
     if nCode = HSHELL_WINDOWDESTROYED then
     begin
          AssignFile(nFile,LogFile);
          Append(nFile);
          GetWindowText(wParam,Title,256);
          ProcId := GetWindowThreadProcessId(wParam,nil);
          ProcHnd := OpenProcess(PROCESS_ALL_ACCESS,False,ProcId);
          GetModuleFileName(ProcHnd,Namef,256);
          CloseHandle(ProcHnd);
          Str := 'Disattivato "' + Title + '" in data ' + DateTimeToStr(Now) +
' da: [' + Namef + '].';
          Writeln(nFile,Str);
          Flush(nFile);
          CloseFile(nFile);
     end;
     Result := CallNextHookEx(HookAdr,nCode,wParam,lParam);
end;
procedure AvviaLog(Log: PChar); stdcall;
{
 Questa procedura inserisce la funzione "MonLog" nella catena degli Hook di
sistema
 di Windows. Accetta come parametro 1 PChar:
 Log : Nome completo di percorso del file in cui sarà salvato il log
}
begin
     LogFile := String(Log);
     HookAdr := SetWindowsHookEx(WH_SHELL,@MonLog,hInstance,0);
end;
procedure StopHook; stdcall;
{
 Questa procedura rimuove la funzione "MonLog" dalla catena degli Hook di
sistema
 di Windows;
}
begin
     UnHookWindowsHookEx(HookAdr);
end;
exports
  MonLog, AvviaLog, StopHook;
begin
end.
Prima di innescare un putiferio specifico che non sono un programmatore
"commerciale", nel senso che non vendo i miei programmi ma programmo per puro
sfizio, lavorando in tutt'altro campo, quindi questo mio prg,
se mai dovesse vedere la luce, rimarrà relegato sul mio computer.
Il codice di cui sopra, oltre a non funzionare, a volte mi crasha il sistema
facendo apparire un agghiacciante messaggio d'errore in modo testo tipo:
Errore irreversibile in........
Contattare il produttore del software.... ecc. ecc.
Siccome il suddetto produttore del software non sa che pesci pigliare mi
chiedevo se qualcuno di voi,
o divini guru della programmazione, potesse illuminarmi (dove sbaglio, come
posso fare ecc.).
Un grazie anticipato a tutti.
Ciao, Marco.
-- 
Posted from  [62.98.40.24] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Riporto il sorgente della DLL che contiene l'hook:
non riporto il codice dell'hook perchè vado subito al dunque.
I problemi sono molteplici.
Allora, essendo un hook di sistema, windows inietta la procedura di callback
(cioè la tua "MonLog" ) nel processo interessato dall'hook installato.
A questo punto, le variabili esterne alla procedura di callback, perdono
significato, quindi la tua "LogFile" non so proprio che valori prende.
Oltre a questo, sbagli nelle operazioni su file.
Tu usi la "Assign" per assegnare il tuo LogFile alla variabile "nfile", poi
usi la "Append" per appendere un record oltre a quello già esistente.
Non gioco spesso con queste funzioni, ma la "Append" immagino dia esito
positivo quando esiste già il file creato magari con "Rewrite" o con un
altro sistema, l'importante che esiste.
Continuando giù, ho trovato altri problemi. Il primo i puntatori.
Poi non ho capito bene cosa volevi fare con queste 3 righe:
ProcId := GetWindowThreadProcessId(wParam,nil);
ProcHnd := OpenProcess(PROCESS_ALL_ACCESS,False,ProcId);
GetModuleFileName(ProcHnd,Namef,256);
le prime 2 ti sono servite per utilizzare la GetModuleFileName ?
Immagino di si, perchè sotto non ti vai a ripescare i dati ottenuti. Però,
se leggi riguardo la GetModuleFileName, dice che se al primo parametro passi
NULL, in questo caso 0, ti restituisce il nome del file appartenente al
processo stesso, che in questo caso è il processo sove si trova la hookproc
( MonLog ) iniettata.
Quindi tutta la fatica sopra fatta, non serve. Rimane solo la terza riga,
così scritta:
GetModuleFileName(0, @Namef, 256);
A parte tutto ciò ( se è la prima volta che scrivi un hook va
benissimo....anzi, pure troppo ) secondo me non è bellissimo il sistema del
file.
E' solo un consiglio oltre ad un suggerimento per un successivo hook.
Nel tuo caso puoi anche lasciare il file, visto che non è poi pesante perchè
nell'unità di tempo non vengono create e distrutte tantissime finestre, ma
se fosse un hook  di messaggi  ( ad esempio ) allora credo che certe
operazioni su file siano da evitare.
Esiste sempre la comunicazione interprocesso che utilizza la memoria, molto
più veloce di certe operazioni su file.
Poi è una questione di abitudine. Ovviamente l'utilizzo di un file è molto
più semplice dell'interprocesso, ma una volta capita la cosa utilizzerai
sempre quest'ultimo, anche quando non c'è bisogno !! ehhehe
Per dire, il tuo hook , una volta ricavati i dati ( che poi tu salvi su
file ) li inviava alla tua applicazione utilizzando il messaggio WM_COPYDATA
( messaggio utile per una comunicazione interprocesso ).
La tua applicazione, riceveva il messaggio e tramite il rispettivo handler,
scriveva i dati su file o magari in uno stream ........ alla fine, o ad
intervalli di tempo, li poteva riversare su file.
Finito tutto, si chiudeva il file.
Insomma bastava una sola apertura e chiusura del file interessato.
Ok, ora ti saluto e buona domenica.
Non ti ho postato il codice corretto ( o perlomeno funzionante ).
In tal caso scrivimi in privato e te lo posto.
Ciao...
Antonio Tarolla

 Ok, ora ti saluto e buona domenica.
Grazie ancora e buona domenica anche a te.
Ciao. Marco

 volta che il fottuto hook funziona  (se mai funzionerà) passerò ad
affinare il resto.
come ti ho detto sopra, l'hook funziona. Se mi scrivi in privato, ti posso
mandare anche qualche esempio che ho, darti qualche suggerimento anche se
non mi ritengo un esperto di hook.
Ti saluto....a risentirci. Ciao...
Antonio Tarolla