Как мне получить HMODULE для исполняемого в данный момент кода? - PullRequest
35 голосов
/ 17 февраля 2009

У меня есть статическая библиотека, которая может быть связана либо с .exe, либо с .dll. Во время выполнения я хочу, чтобы только мои библиотечные функции получили HMODULE для любой вещи, с которой был связан статический код библиотеки.

В настоящее время я использую следующий трюк (вдохновленный этим форумом ):

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

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

Есть ли лучший способ сделать это, который выглядит не так глупо?

(Примечание: цель этого состоит в том, чтобы загрузить некоторые ресурсы Win32, к которым, как я знаю, мои пользователи будут подключены одновременно с моей статической библиотекой.)

Ответы [ 4 ]

50 голосов
/ 17 февраля 2009
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
  HMODULE hModule = NULL;
  GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
    (LPCTSTR)GetCurrentModule,
    &hModule);

  return hModule;
}
29 голосов
/ 17 февраля 2009

__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

3 голосов
/ 17 февраля 2009

Я бы посмотрел на 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;
}

Я не пробовал, но я думаю, что это будет делать то, что вы хотите.

0 голосов
/ 17 февраля 2009

HMODULE - HINSTANCE - базовый адрес модуля. Итак, я посмотрю, как это работает. Но если вам нужен только HMODULE исполняемого файла, почему бы не перечислить все HMODULE в процессе (EnumProcessModules). У одного из них будет привязан ваш .lib.

Ограничение, которое я вижу, заключается в том, что вы понятия не имеете, из какой DLL или EXE происходит ваш .lib. Возможно, вы захотите сравнить HMODULE (базовые адреса) с _ReturnAddress, который вы получаете из вашего .lib. Ваш .lib будет принадлежать старшей HMODLUE меньше, чем ваш _ReturnAddress

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...