Newsgroup: it.comp.lang.delphi
Titolo: Usare una funzione esterna in un hook

Un saluto a tutti.
Ho una dll che installa un hook ed espone, tra le altre, una funzione 
che vorrei far eseguire all'hook stesso. La mia idea sarebbe questa:
1) la mia dll, prima della installazione dell'hook, salva da qualche 
parte (un memory mapped file ad esempio...) il puntatore alla funzione 
che desdiero sia eseguita dall'hook.
2) nell'hook controllo il msg e, se devo gestirlo, leggo il puntatore 
salvato sul mmf ed eseguo la funzione indicata dal puntatore.
Le domande...
a) questo meccanismo può funzionare oppure è una kazzata?
Se si, why?
b) qualora funzionasse, presumo che la funzione di callback debba essere 
esposta, o sbaglio?
c) esistono alternative a questa?
Postilla
Lo so che mo state pensando: "ke k@@@o di problema hai che richiede 
questo circolo vizioso?"
Ho una dll non fatta che gestisce un device e lo blocca con una critical 
section, ma se parte una specifica app *deve* poter usare il device e 
l'unico modo che ho per fare 'sta cosa è dire alla istanza della dll che 
ha aperto la connesione al device di chiuderla.... :(
AS


Potrebbe anche andare, provala.
L'alternativa e' quella in genere usata per gli Hook globali:
nella Dll dell'Hook esponi una funzione che, chamata dalla tua appl., passa
l'handle della win. a cui l'Hook dovra' postare i Msg quanto intercetta
qualcosa di interesse. Tale Handle andra' assegnato ad un puntatore^ di una
variabile mappata in memoria, per il problema degli spazi degli indirizzi.
il link con la Dll deve essere di tipo statico, non puoi metterla nelle
"uses nomedll".
Quando l'hook raccoglie qualcosa di buono, fa un PostMessage usando
puntatore^ come handle, WM_USER+NUM ed in wp e lp ci metti tue info utili.
Sono stato breve, mi rendo conto...
Ciao Giorgio

 Sono stato breve, mi rendo conto...
non breve: sintetico. ;)
AS


Secondo me non ne hai bisogno. Il codice della dll, cs code segment, della
dll è unico. Quello che cambia è il data segment.
Ti devi preoccupare solo se hai delle variabili globali di renderli globali,
se ne hai bisogno, da tutti i processi in cui la dll agisce. (Memory Mapped
File)
Discorso totalmente diverso se la funzione che vuoi richiamare è una
callback impostata dalla tua app che usa la dll. Ma hai detto che la tua
stessa dll espone già dentro la funzione che vuoi venga usata.
Leggo ora la tua postilla.
Mi viene in mente un'altra soluzione. Molto molto tecnica e critica: si può
hookare la funzione di una dll. Come si hookava un interrupt in ms-dos.
Se fai un hook su CreateProcess(EX), e CloseHandle, insomma sulle due
funzioni che avviano e chiudono un processo, potresti sapere perfettamente
quando un programma, quello che vuoi, viene lanciato.
Me ne interessai tempo fa. E' più una procedura da hacker. Se cerchi api
hook trovi sicuramente qualcosa... di molto interessante. Dovrei avere anche
qualcosa da qualche parte, se ti interessa la tecnica e non trovi molto
scrivimi che ti mando quello che ho.
C'erano anche dei componenti scritti da un certo madshi che facevano
facilmente sto lavoro. (cerca madshi api hook, anche delphi dll inject)
Comunque sono tecniche estreme.
Ciao
Giuseppe

 File)
Questo non lo sapevo ed e' interessante... in sostanza se ho capito bene
basta rendere pubblica la funzione dell'applicazione e richiamarla dalla Dll
(come external), si eviterebbe l'uso dei file mapp. in memoria e casini
vari.
Be' fatemi sapere se la cosa funziona.
Giorgio Padoan

 vari.
Aspetta, non capisco.
Una dll espone le suefunzioni (External).
Una applicazione caricando quella dll ricava i puntatori a quelle funzioni
esposte (Getprocaddress).
Se una dll si avvale di una sua funzione esposta l'azione si svolgerà sempre
dentro quella dll. L'applicazione non c'entra.
Se una dll viene caricata da più processi il suo codice sarà condiviso da
entrambi i processi. Sarebbe illogico se una dll dovesse caricarsi in
memoria tutte le volte che venisse aperta una nuova istanza. Basta solo la
prima.
Quelli che cambiano da processo a processo sono il segmento dati e lo stack.
Altrimenti ci sarebbe un bell'intreccio di dati.
Se la dll vuole condividere dati fra dueo più processi deve usare un file
mapping.
Una libreria usata per creare un hook a livello di sistema va ad invadere
ogni processo. Se contiene variabili globali queste non avranno mai lo
stesso dato: varieranno a seconda del processo in cui viene invocata la
callback.
Ma il codice è sempre quello, non cambia. Infatti se fai un
readprocessmemory o un writeprocessmemory, puoi modificare il segmento
codice della dll (Puoi usarlo anche per conservare dati) e questo sarà
identico per ogni istanza della dll (non consigliabile).
Ma tutto sto discorso se la dll viene usata da un solo processo può essere
evitato. L'interscambio di dati fra i due elementi è molto più semplice.
Rileggo, e ammetto che se mi immedesimo in chi mi vuol capire, non mi
capisco. :-D
Ciao!
Giuseppe

 Comunque sono tecniche estreme.
"A casi estremi applichiamo tecniche estreme" ;)
Bye&Tnx
AS


Ok.
Fai così.
1. Nella dll esponi due funzioni: sia una apertura sia una chiusura del
device. L'apertura ti restituirà l'handle, la chiusura vorrà l'handle.
2. Crea un messaggio comune sia alla tua app, sia alla dll. Nella dll crea
tale messaggio dentro il begin di inizializzazione così da farlo creare in
ogni processo in cui entra da sola.
3. Nella tua app cattura ogni messaggio che arriva al tuo thread principale.
Application.OnMessage. Cattura ovviamente il messaggio che hai preparato tu.
4. Da qualsiasi istanza della dll, quando vuoi aprire il device mandi in
broadcast il messaggio con impostato in wParam o lParam un tuo
identificativo per aprire il device.
5. Stessa cosa quando vuoi chiudere il device.
6. Ti ho mandato alcuni articoli e esempi su come si hooka una api. Ma il
tuo indirizzo è corretto? Vabbe, li mando lo stesso...
Ciao
Giuseppe

 tuo indirizzo č corretto? Vabbe, li mando lo stesso...
aggiugi "to" tra zza e il simbolo @.
ciao&grazie
AS


Ciao Giuseppe,
non e' proprio cosi' semplice anche se viene creata una soloa istanza da
un'unica appl., cerco di spiegarmi:
Se tenti di passare il valore di una variabile dell'appl. all'Hook globale
memorizzandolo in una variabile dell'Hook, ad esempio come parametro in una
funzione "Start" esposta dall'Hook, questo non si comportera' come globale
ma come locale all'appl. nel senso che catturera' solo gli msg. dell'appl.
enon tutti gli altri. Della cosa sono certo, avendolo testata di persona, da
quanto ho capito il meccanismo agisce a livello del compilatore nel senso
che in questo caso il segmento di memoria dell'hook lo fa coincidere con
quello dell'applicazione.
Sai bene che l'hook globale comunica con l'applicazione tramite postmessage,
allora rimangono 2 possibilita':
- se non c'e' bisogno di velocita' l'hook, quando ha bisogno, invia un Msg
in BROADCAST: e' lento in quanto tutte le Win.principali ricevono il Msg e
lo debbono "digerire".
- in caso contrario (era il mio caso) l'appl. deve fornire il suo handle in
modo che il Msg arrivera' solo a lei, conservando la velocita' del PC. Come
dicevo sopra quando l'appl. esegue la funzione "Start" esposta dalla dll e
passa il suo handle come parametro il codice della Start deve memorizzarlo
in un mmf, permettendo di conservare la globalita' dell'Hook.

 un'unica appl., cerco di spiegarmi:
[cut]
Ciao Giorgio,
certo, mi sono espresso male. :-)
Quando dico che l'hook viene usato da 1 sola applicazione, intendevo un hook
non di sistema.
Un hook di sistema va ad invadere gli altri processi, anche se la dll viene
istanziata solo 1 volta, dalla applicazione che ha creato l'hook.
Ma se l'hook è in locale solo per quella app, oltre al fatto che non vedo
più l'esigenza di una dll esterna per contenerlo, i dati potranno essere
interscambiati, anche per mezzo di una callback, a mo' di evento, fra i due
elementi (applicazione-dll).
A sto punto mi son perso! :-)
Non ricordo più se Alberto aveva necessariamente bisogno di un hook di
sistema.
Sei un ottimizzatore di risorse di prima categoria! :-)
Con le risorse attuali un messaggino in più per ogni app da ignorare, quello
mandato in broadcast, non appesantisce il sistema più di tanto... a meno che
non sia mandato un broadcast ogni millisecondo! Ho consigliato quello perché
personalmente l'idea di andar a creare, chiudere, gestire e controllare un
MMF, mi darebbe molto più fastidio. Si dovrebbe anche ricavare il puntatore
dell'MMF, facendo i relativi controlli di sicurezza,  ogni volta in cui la
dll per mezzo dell'hook di sistema entrerebbe nell'area di un nuovo
processo.
Ciao! :-)
Giuseppe

 MMF, mi darebbe molto piů fastidio.
Ed hai fatto bene, avrei dovuto farlo anch'io ma m'ero dimenticato che si
poteva usare il Broadcast nel Post
Alla prossima, Giorgio