Статья: Работа с процессами в С/С++. Основные приемы
DWORD GlblcntUsage; //общее число ссылок на этот модуль
DWORD ProccntUsage; //число ссылко в контексте процесса,
//по идентификатору которого был создан
//снэпшот. Если равен 65535 - модуль подгружен
//неявно
BYTE *modBaseAddr; //адрес модуля в контексте процесса
DWORD modBaseSize; //размер проекции
HMODULE hModule; //ссылка на модуль
char szModule[MAX_MODULE_NAME32 + 1]; //Имямодуля
char szExePath[MAX_PATH]; //Полныйпутькмодулю
} MODULEENTRY32,*PMODULEENTRY32,*LPMODULEENTRY32;
Обратитевнмание: ссылканамодуль (параметр hModule) - этопервыйбайтДОС-заголовка! Таким образом, мы получаем возможность работать с проекцией при некотором знании структуры PE-файлов. В частности мы можем прочиатать таблицу импорта, и, как правило, - даже переписать ее (это используется при перехвате АПИ). Параметр szExePath имеет свой "заскок" - иногда полный путь к модулю возвращается со странными вставками и, например, всесто "c:windowssystem32advapi32.dll" я иногда получаю "c:x86_proc_winsyspathadvapi32.dll". Как правило для системных задач средней сложности (перехват апи, или, наоборот, перехват стелсов) всего вышеописанного хватает. Но на этом возможности toolhelp не исчерпываются и теперь мы побегаем по потокам! Работа с потоками несколько отличается от работы с модулями - даже если мы сделаем снимок, задав идентификатор какого-либо процесса, функция Thread32Next не остановится, пока не пробежится по ВСЕМ потокам в системе. Поэтому мы должны проверять, к какому процессу принадлежит поток - благо, в структуре THREADENTRY32 есть член th32OwnerProcessID - идентификатор породившего поток процесса. Таким образом:
int EnumerateThreads(DWORD PID)
{
//Начнем с создания снимка
HANDLE pThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PID);
bool bIsok = false;
//Структура, описывающая поток
THREADENTRY32 ThrdEntry;
//ставимразмер
ThrdEntry.dwSize = sizeof(THREADENTRY32);
//Беремпервыйпоток
bIsok = Thread32First(pThreadSnap, &ThrdEntry);
//и бегаем по всем потокам...
while (bIsok)
{
//проверяем, тому ли процессу принадлежит поток
if (ThrdEntry.th32OwnerProcessID == PID)
{