Как мне получить HMODULE для исполняемого в данный момент кода?
У меня есть статическая библиотека, которая может быть связана либо в .exe
или .dll
, Во время выполнения я хочу, чтобы только мои библиотечные функции получили HMODULE
для чего бы то ни было статический код библиотеки был связан с.
В настоящее время я использую следующий трюк (вдохновленный этим форумом):
const HMODULE GetCurrentModule()
{
MEMORY_BASIC_INFORMATION mbi = {0};
::VirtualQuery( GetCurrentModule, &mbi, sizeof(mbi) );
return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}
Есть ли лучший способ сделать это, который не выглядит таким хакерским?
(Примечание: цель этого состоит в том, чтобы загрузить некоторые ресурсы Win32, к которым, как я знаю, мои пользователи будут подключены одновременно с моей статической библиотекой.)
4 ответа
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModule,
&hModule);
return hModule;
}
__ImageBase
является сгенерированным компоновщиком символом, который является заголовком DOS модуля (только MSVC). Из этого вы можете привести его адрес к HINSTANCE
или же HMODULE
, Так что это удобнее, чем проходить через API.
Так что вам просто нужно сделать это:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
От http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
Я бы посмотрел на GetModuleHandleEx()
используя флаг GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
, Похоже, вы можете изменить свой GetCurrentModule()
называть эту рутину вместо VirtualQuery()
и передать адрес GetCurrentModule()
как 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;
}
Я не пробовал это, но я думаю, что это будет делать то, что вы хотите.
#if _MSC_VER >= 1300 // for VC 7.0
#ifndef _delayimp_h
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif
#endif
...
HMODULE module()
{
#if _MSC_VER < 1300 // earlier than .NET compiler (VC 6.0)
MEMORY_BASIC_INFORMATION mbi;
static int address;
;::VirtualQuery(&address, &mbi, sizeof(mbi));
return reinterpret_cast(mbi.AllocationBase);
#else // VC 7.0
// from ATL 7.0 sources
return reinterpret_cast(&__ImageBase);
#endif
}
Подробнее здесь https://www.apriorit.com/dev-blog/74-hmodule-hinstance-handle-from-static-library-in-c
HMODULE - это HINSTANCE - базовый адрес модуля. Итак, я посмотрю, как это работает. Но если все, что вам нужно, это HMODULE исполняемого файла, почему бы не перечислить все HMODULE в процессе (EnumProcessModules). У одного из них ваш.lib будет связан.
Ограничение, которое я вижу, состоит в том, что вы понятия не имеете, из какой DLL или EXE происходит ваш.lib. Возможно, вы захотите сравнить HMODULE (базовые адреса) с _ReturnAddress, который вы получаете из вашего.lib. Ваш.lib будет принадлежать к старшей HMODLUE меньше, чем ваш _ReturnAddress