2009-02-17 17 views
31

Mam statyczną bibliotekę, która może zostać połączona z .exe lub .dll. W czasie wykonywania chcę mieć wszystkie funkcje biblioteczne, aby uzyskać HMODULE dla każdej rzeczy, do której został dołączony kod biblioteki statycznej.Jak uzyskać HMODULE dla aktualnie wykonywanego kodu?

Używam obecnie następujący trick (inspirowaną od this forum):

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

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

Czy istnieje lepszy sposób na to, że nie wygląda tak hacky zrobić?

(Uwaga: Celem jest to, aby załadować niektórych zasobów Win32 że znam moje użytkownicy będą mieli połączone w tym samym czasie, co moim statycznej biblioteki.)

+0

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

Odpowiedz

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

    return hModule; 
} 
+0

Cool. Pamiętam, że kiedy napisałem funkcję GetCurrentModule(), musieliśmy obsługiwać Windows 2000. Dlatego użyłem haka VirtualQuery() zamiast GetModuleHandleEx(). – pauldoo

+0

GLAD, aby pomóc. Z ciekawości, dlaczego wolisz moje rozwiązanie od wersji __ImageBase? –

+1

Prawdopodobnie z powodu niezrozumienia, w jaki sposób system Windows naprawia adresy symboli. – MSN

3

będę patrzeć na GetModuleHandleEx() pomocą flaga GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS. Wygląda na to, że możesz zmienić swój GetCurrentModule(), aby wywołać tę procedurę zamiast VirtualQuery() i przekazać adres GetCurrentModule() jako argument 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; 
} 

I nie spróbować, ale myślę, że będziemy robić to, co chcesz.

-4

HMODULE to HINSTANCE to adres bazowy modułu. Tak więc chciałbym zobaczyć, jak to działało. Ale jeśli chcesz tylko HMODULE pliku wykonywalnego, dlaczego nie wyliczyć wszystkie HMODULE w procesie (EnumProcessModules). Jeden z nich będzie miał dołączone twoje .lib.

Ograniczeniem, które widzę, jest to, że nie masz pojęcia, która biblioteka DLL lub EXE pochodzi z .lib. Możesz porównać HMODULE (adresy bazowe) z _ReturnAddress, który otrzymasz ze swojego .lib. Twój lib będzie należał do najwyższych HMODLUE mniejszy niż _ReturnAddress

+0

Wyliczanie listę modułów jest bardzo nieefektywne, a nie tak czysty jak wywołanie GetModuleHandleEx. Zobaczmy; uzyskaj odpowiedź, której potrzebuję, korzystając z pojedynczego, szybkiego wywołania API lub przechodź przez potencjalnie kilkadziesiąt modułów, wykonując porównania ciągów (BARDZO drogie!). Myślę, że wezmę skrót. –

25

__ImageBase jest łącznik generowane symbol, który jest nagłówek DOS modułu (tylko MSVC). Z tego możesz przesłać jego adres na adres HINSTANCE lub HMODULE. Jest to wygodniejsze niż przejście przez interfejs API.

Więc po prostu trzeba to zrobić:

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

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

+0

Zgodnie z linkiem w moim pierwotnym pytaniu, __ImageBase jest tylko preferowanym adresem ładowania, nie zawsze rzeczywistym adresem ładowania. – pauldoo

+1

Wątpisz w Raymonda Chen? Dyskusja na łączu demonstruje fundamentalne nieporozumienie dotyczące stałej linkera, ale ostateczny komentarz jest poprawny. –

+4

Błąd ... __ImageBase jest symbolem. Jeśli nie zostanie naprawiony, gdy załaduje się .dll lub .exe, żaden inny symbol i wszystko nie pęknie. Dlatego też można z niego korzystać, ponieważ jego adres jest naprawiony w czasie ładowania obrazu. – MSN

Powiązane problemy