2009-02-17 6 views
31

Ho una libreria statica che può essere collegata a .exe oa .dll. In fase di esecuzione, desidero solo alcune delle funzioni della mia libreria per ottenere il valore HMODULE per qualsiasi cosa al codice della libreria statica sia stato collegato.Come ottengo HMODULE per il codice attualmente in esecuzione?

Attualmente uso il seguente trucco (ispirato da this forum):

const HMODULE GetCurrentModule() 
{ 
    MEMORY_BASIC_INFORMATION mbi = {0}; 
    ::VirtualQuery(GetCurrentModule, &mbi, sizeof(mbi)); 

    return reinterpret_cast<HMODULE>(mbi.AllocationBase); 
} 

C'è un modo migliore per fare questo che non guarda in modo hacky?

(Nota: Lo scopo di questo è quello di caricare alcune risorse Win32 che conosco i miei utenti avranno collegato in allo stesso tempo come la mia libreria statica.)

+0

correlati: http://stackoverflow.com/q/119706/946850 – krlmlr

risposta

42
HMODULE GetCurrentModule() 
{ // NB: XP+ solution! 
    HMODULE hModule = NULL; 
    GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
    (LPCTSTR)GetCurrentModule, 
    &hModule); 

    return hModule; 
} 
+0

Freddo. Ora ricordo che quando ho scritto la mia funzione GetCurrentModule() dovevamo supportare Windows 2000. Per questo motivo ho usato l'hacking VirtualQuery() invece di GetModuleHandleEx(). – pauldoo

+0

GLad per aiutare. Per curiosità, perché preferisci la mia soluzione rispetto a quella di __ImageBase? –

+1

Probabilmente a causa della mancata comprensione di come Windows risolve gli indirizzi dei simboli. – MSN

3

mi piacerebbe guardare GetModuleHandleEx() utilizzando il flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS. Sembra che tu possa modificare il tuo GetCurrentModule() per chiamare questa routine anziché VirtualQuery() e passare l'indirizzo di GetCurrentModule() come argomento lpModuleName.

ETA:

const HMODULE GetCurrentModule() 
{ 
    DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; 
    HMODULE hm = 0; 
    ::GetModuleHandleEx(flags, reinterpret_cast<LPCTSTR>(GetCurrentModule), &hm); 
    return hm; 
} 

Non ho provato, ma penso che farò quello che vuoi.

-4

HMODULE è l'HINSTANCE è l'indirizzo di base del modulo. Quindi, vedrei come ha funzionato. Ma se tutto ciò che si desidera è l'HMODULE dell'eseguibile, perché non enumerare tutti gli HMODULE nel processo (EnumProcessModules). Uno di essi avrà il tuo .lib collegato.

La limitazione che vedo è che non hai idea da quale DLL o EXE provenga il tuo .lib. Potresti voler confrontare gli HMODULE (indirizzi di base) con il _ReturnAddress che ricevi dal tuo .lib. Il tuo lib apparterrà al più alto HMODLUE più piccolo della tua _ReturnAddress

+0

enumerazione un elenco dei moduli è molto inefficiente, e non quasi in ordine come chiamare GetModuleHandleEx. Vediamo; ottenere la risposta di cui ho bisogno con una singola, veloce chiamata API, o loop attraverso potenzialmente dozzine di moduli, eseguendo confronti tra stringhe (MOLTO costosi!) mentre vado. Penso che prenderò la scorciatoia. –

25

__ImageBase è un simbolo generato linker che è l'intestazione DOS del modulo (solo MSVC). Da questo puoi trasmettere il suo indirizzo a HINSTANCE o HMODULE. Quindi è più conveniente che passare attraverso un'API.

quindi basta fare questo:

EXTERN_C IMAGE_DOS_HEADER __ImageBase; 
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) 

Da http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx

+0

Secondo il collegamento nella mia domanda originale, __ImageBase è solo l'indirizzo di caricamento preferito, non sempre l'indirizzo di caricamento effettivo. – pauldoo

+1

Hai dubbi su Raymond Chen? La discussione al link dimostra un fondamentale fraintendimento di una costante del linker, ma il commento finale è corretto. –

+4

Err ... __ImageBase è un simbolo. Se non è stato corretto quando è stato caricato .dll o .exe, nessuno dei due simboli e tutto si spezzerebbe. Pertanto, è valido utilizzarlo poiché il suo indirizzo è stato risolto al momento del caricamento dell'immagine. – MSN