2009-02-17 11 views
31

Tengo una biblioteca estática que puede vincularse ya sea a .exe o .dll. En el tiempo de ejecución, quiero que todas las funciones de mi biblioteca obtengan el HMODULE para lo que sea que se haya vinculado el código de la biblioteca estática.¿Cómo obtengo el HMODULE para el código que se está ejecutando actualmente?

Actualmente utilizo el siguiente truco (inspirado en this forum):

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

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

¿Hay una mejor manera de hacer esto que no se ve tan hacky?

(Nota: El propósito de esto es para cargar algunos recursos Win32 que sé que mis usuarios se han vinculado al mismo tiempo que mi biblioteca estática.)

+0

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

Respuesta

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

    return hModule; 
} 
+0

Cool. Ahora recuerdo que cuando escribí mi función GetCurrentModule() teníamos que admitir Windows 2000. Por eso utilicé el hack VirtualQuery() en lugar de GetModuleHandleEx(). – pauldoo

+0

GLad para ayudar. Por curiosidad, ¿por qué preferiste mi solución a la de __ImageBase one? –

+1

Probablemente debido a no entender cómo Windows corrige las direcciones de símbolo. – MSN

3

me vería en GetModuleHandleEx() utilizando el flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS. Parece que puede cambiar su GetCurrentModule() para llamar a esta rutina en lugar de VirtualQuery(), y pasar la dirección de GetCurrentModule() como el argumento 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; 
} 

Yo no lo probamos, pero creo que va a hacer lo que quiere.

-4

El HMODULE es el HINSTANCE es la dirección base del módulo. Entonces, vería cómo funcionó. Pero si todo lo que quiere es el HMODULE del ejecutable, ¿por qué no enumerar todos los HMODULE en el proceso (EnumProcessModules)? Uno de ellos tendrá su .lib vinculado.

La limitación que veo es que no tiene idea de qué DLL o EXE proviene su .lib. Es posible que desee comparar los HMODULE (direcciones base) contra _ReturnAddress que obtiene de .lib. Su Lib pertenecerá a la más alta HMODLUE más pequeño que su _ReturnAddress

+0

enumerar una lista de los módulos es muy ineficiente, y no es tan ordenado como llamar a GetModuleHandleEx. Veamos; Obtenga la respuesta que necesito con una sola y rápida llamada API, o pase por docenas de módulos, realizando comparaciones de cadenas (¡MUY caras!) sobre la marcha. Creo que tomaré el atajo. –

25

__ImageBase es un símbolo generada conector que es la cabecera del módulo de DOS (sólo MSVC). Desde allí, puede enviar su dirección a HINSTANCE o HMODULE. Por lo tanto, es más conveniente que pasar por una API.

lo que sólo tiene que hacer esto:

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

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

+0

De acuerdo con el enlace en mi pregunta original, __ImageBase es solo la dirección de carga preferida, no siempre la dirección de carga real. – pauldoo

+1

¿Dudas de Raymond Chen? La discusión en el enlace demuestra un malentendido fundamental de una constante del enlazador, pero el comentario final es correcto. –

+4

Err ... __ImageBase es un símbolo. Si no se arregló cuando se carga el .dll o .exe, tampoco se rompería ningún otro símbolo y todo. Por lo tanto, es válido usarlo ya que su dirección está arreglada en el momento de cargar la imagen. – MSN

Cuestiones relacionadas