Domanda

La mia domanda non è esattamente la stessa di questa (non è teorica, c'è solo un thread principale senza loop di messaggi, InitInstance ed ExitInstance non sono chiamate appropriate).

Sto usando un'app console senza loop di messaggi; questa app carica un exe con la funzione LoadLibrary, in modo che possa usare le sue funzioni esportate. Cattive notizie: la funzione DllMain dell'exe non viene chiamata (e ho verificato le tabelle dei simboli, usando un file def, DllMain appare correttamente); dice il documento viene chiamato se il modulo caricato è una DLL (anche cattivo).

Quali sono le condizioni (se esistono) che potrebbero portare all'esecuzione della funzione DllMain dell'exe quando viene chiamato LoadLibrary (e forse di nuovo quando viene chiamato FreeLibrary)?

Cordiali saluti

È stato utile?

Soluzione

La condizione più ovvia è che il processo che chiama LoadLibrary () ottenga esplicitamente GetProcAddress (" DllMain ") e quindi lo chiami.

Altri suggerimenti

Le condizioni sono:

1) Il file binario caricato è stato compilato come DLL (quando si utilizza gcc / ld significa utilizzare l'opzione --shared ; se si utilizza --shared , il file risultante essere una dll e non funzionerà, vedi sotto)

2) IMAGE_FILE_DLL è impostato nell'intestazione del file PE del file binario da caricare. Se è impostato, il file è una dll e il linker di Windows chiamerà la sua funzione DllMain () quando collega questo file al tuo programma (non importa come sia collegato - LoadLibrary () in fase di esecuzione o -llibraryname al momento della compilazione). Per questo il file deve anche soddisfare (1). Ma con questo flag il file binario che viene caricato non sarà eseguibile. Se IMAGE_FILE_DLL non è impostato, DllMain () non verrà chiamato quando il file viene caricato nel programma.

Compilare la dll con --shared e quindi rimuovere manualmente IMAGE_FILE_DLL dalla sua intestazione (cioè usando l'editor esadecimale) non funzionerà - quando lo esegui, solo DllMain () verrà eseguito e fdwReason sarà un numero non definito ( 0x28ffd4 sulla mia macchina).

Aggiorna

Tutti i file DLL ed EXE su Windows sono file PE, la differenza è in che modo sono collegati e quali flag sono impostati nelle loro intestazioni. Questo è il motivo per cui scrivo file caricato , non dll caricato .

L'ultimo paragrafo descrive anche lo scenario in cui si compila il file come dll, quindi lo si trasforma in exe rovinando la sua intestazione. Non funziona.

La denominazione non ha nulla a che fare con questo (puoi scegliere qualsiasi nome, e con alcuni pexports + dlltool puoi creare una libreria di importazione per un file .exe e essere in grado di collegarlo come -lexenamewithoutextension

Per chiarire:

  • se lo compili senza --shared :
    • IMAGE_FILE_DLL non verrà impostato in esso, sarà eseguibile, ma DllMain () NON verrà chiamato quando lo colleghi.
  • se lo compili con --shared :
    • IMAGE_FILE_DLL verrà impostato in esso, NON sarà eseguibile, ma DllMain () verrà chiamato quando lo colleghi.
  • se lo compili senza --shared , quindi attiva il flag IMAGE_FILE_DLL in esso manualmente:
    • NON sarà più eseguibile e nessun DllMain () verrà chiamato quando lo colleghi.
  • se lo compili con --shared , quindi disattiva manualmente il flag IMAGE_FILE_DLL :
    • sarà eseguibile, ma DllMain () verrà eseguito invece di main () e DllMain () NON verrà chiamato quando lo colleghi.

In effetti il ??Nome "quot DainMain" della funzione è completamente ignorata da Windows (la vecchia documentazione API Windows di Windows NT 3.x lo affermava esplicitamente).

Quando viene caricata una DLL non viene chiamata la funzione DllMain () ma la funzione che si trova nel punto di ingresso del file.

Naturalmente il linker creerà il file DLL in modo che DllMain () sia questa funzione.

Tuttavia, per i file EXE la funzione di inserimento (che chiamerà WinMain ()) si trova nel punto di ingresso.

Quindi è ovvio che Windows non può chiamare questa funzione quando si carica il file EXE come DLL.

Completamento della buona risposta di MSalters :

Quindi, quindi, chiama il " fake " DllMain con DLL_XXX_ATTACH subito dopo LoadLibrary e con DLL_XXX_DETACH appena prima di FreeLibrary ed effettua manualmente le altre chiamate.

Un'altra seguente implementazione sarebbe quella di costruire e caricare una DLL di interfaccia che potesse richiamare automaticamente l'EXE sul suo falso DllMain (non so se potesse funzionare); ma può essere più complicato della semplice chiamata manuale del falso DllMain in diversi casi. (impossibile LoadLibrary in un DllMain)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top