Как узнать, действителен ли дескриптор модуля Windows?

StackOverflow https://stackoverflow.com/questions/1111820

  •  12-09-2019
  •  | 
  •  

Вопрос

Модуль можно выгрузить, так как я могу точно определить, находится ли он еще в памяти?У меня есть дескриптор, полученный из GetModuleHandle.Когда я попытался называть Gethandleinformation, я вижу ошибку 0xc0000008 - «Была указана неверная ручка». Это произошло до того, как его можно было разгрузить.

Это было полезно?

Решение

Термин «дескриптор» здесь немного перегружен — множество различных классов объектов в Win32 API называются «дескрипторами».

GetHandleInformation используется для дескрипторов объектов ядра — файлов, ключей реестра, мьютексов и т. д.

HMODULE, возвращаемый GetModuleHandle, используется загрузчиком и не является фактическим объектом ядра, поэтому GetHandleInformation завершается с ошибкой.Однако ни один из флагов, которые вы получаете в GetHandleInformation, не имеет смысла для HMODULE.

Если вы хотите проверить, загружен ли HMODULE в память, вы можете просто вызвать GetModuleHandle — этот API должен быть достаточно быстрым, чтобы его можно было вызывать много раз.Однако результат GetModuleHandle может быть недействительным в момент возврата — другой поток мог вызвать FreeLibrary.Лучше убедиться, что DLL остается загруженной.Вы можете сделать это, вызвав LoadLibrary самостоятельно или вызвав GetModuleHandleEx, который увеличит счетчик ссылок DLL.

Другие советы

Два решения:

1

Вызовите GetModuleFileName() в HMODULE.Если модуль загружен, вы получите правильное имя файла.Если он не загружен, вы не получите допустимое имя файла.Обязательно либо установите первый байт возвращаемого массива имен файлов в '\0' перед вызовом GetModuleFileName(), либо проверьте возвращаемое значение.Если вы установите первый байт перед вызовом, вы можете эффективно игнорировать возвращаемое значение и просто рассматривать строку нулевой длины как «не загруженный» сигнал.

TCHAR szModName[MAX_PATH + 1];

szModName[0] = _T('\0');
GetModuleFileName(hMod, szModName, MAX_PATH);

// zero length string if not loaded, valid DLL name if still loaded

2

Вызовите VirtualQuery(), передав HMODULE в качестве адреса для запроса.В качестве эксперимента проделайте это с загруженной библиотекой и с библиотекой, которую, как вы знаете, нужно освободить.Вы обнаружите, что они дают очень разные результаты для возвращенной MEMORY_BASIC_INFORMATION.Я оставляю вам возможность разработать подходящий алгоритм для определения разницы между ними.

Предостережение

Конечно, действует предостережение о том, что другой поток может выгрузить библиотеку во время выполнения любого из этих тестов.По моему опыту, это маловероятно, но это во многом зависит от того, что вы делаете, почему вы это делаете и когда вы это делаете, от пути выполнения программы. Используйте с осторожностью.

Это очень простой API.

PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)

Пример программы:

(PVOID)typedef PIMAGE_NT_HEADERS (NTAPI *RTLIMAGENTHEADER)(PVOID);
RTLIMAGENTHEADER RtlImageNtHeader;
HMODULE hDll = GetModuleHandle("ntdll.dll");
HMODULE hDllTmp = LoadLibrary("ws2_32.dll");
RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hDll,"RtlImageNtHeader");

struct _IMAGE_NT_HEADERS *r,*r2;
r= RtlImageNtHeader(hDllTmp); 
FreeLibrary(hDllTmp);
r2= RtlImageNtHeader(hDllTmp);

//r = NULL
//r2 = return ws2_32 PE Header address
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top