// pImportDesc->FirstThunk, т. к. загрузчик уже изменил этот массив
// при установке всех импортов. Исходный переходник обеспечивает
// доступ к именам функций.
PIMAGE_THUNK_DATA pOrigThunk =
MakePtr ( PIMAGE_THUNK_DATA
hModule ,
pImportDesc->OriginalFirstThunk );
// Получить массив p!mportDesc->FirstThunk, в котором будут
// выполняться подключения и вся черная работа.
PIMAGE_THUNK_DATA pRealThunk = MakePtr ( PIMAGE_THUNK_DATA ,
hModule ,
pImportDesc->FirstThunk );
// Флажок будет устанавливаться из переходника,
// что облегчает его поиск.
DWORD dwCompareOrdinal = IMAGE JDRDINAL_FLAG | dwOrdinal;
// Цикл поиска подключаемых функций.
while ( NULL != pOrigThunk->ul.Function)
{
// Отыскивать только функции, которые импортируются по
// порядковому значению, а не по имени,
if ( IMAGE__ORDINAL_FLAG ==
( pOrigThunk->ul.Ordinal & IMAGE_ORDINAL_FLAG))
{
// Найдена ли функция подключения?
if ( dwCompareOrdinal == pOrigThunk->ul.Ordinal) .
{
// Функция для подключения найдена. Теперь нужно
// изменить защиту памяти на "read-write" (для записи),
// прежде чем перезаписывать указатели функций. Заметьте,
// что ничего не записывается в реальную область
// переходников!
MEMORY_BASIC__IN FORMATION mbi_thunk ;
VirtualQuery ( pRealThunk ,
&mbi_thunk ,
sizeof ( MEMORY_BASIC_INFORMATION) );
if ( FALSE == VirtualProtect ( mbi_thunk.BaseAddress,
rabi_thunk.RegionSize ,
PAGE_READWRITE ,
&mbi_thunk.Protect ))
{
ASSERT ( !"VirtualProtect failed!");
// Здесь приходится фиксировать неуспешное
// выполнение функции (возвращая FALSE),
// предварительно указав причину ошибки.
SetLastErrorEx ( ERROR__INVALID_PARAMETER,
SLE^ERROR );
return ( FALSE);
}
// Сохранить исходные адреса, если требуется
if ( NULL != ppOrigAddr)