ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 09.02.2021

Просмотров: 167

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

7

OC _3к

Windows 95/98: использование ToolHelp32

ToolHelp32 — это семейство функций и процедур, составляющих подмножество Win32 API, которые позволяют получить сведения о некоторых низкоуровневых аспектах работы ОС. В частности, сюда входят функции, с помощью которых можно получить информацию обо всех процессах, выполняющихся в системе в данный момент, а также потоках, модулях и кучах, принадлежащих каждому процессу.

Типы и определения функций ТооlНе1р32 размещаются в модуле ТlНе1р32, поэтому при работе с этими функциями нужно включить его имя в список инструкции uses.

Моментальные снимки

Благодаря многозадачной природе среды Win32 такие объекты, как процессы, потоки, модули и т.п., постоянно создаются, разрушаются и модифицируются. И поскольку состояние компьютера непрерывно изменяется, системная информация, которая, возможно, будет иметь значение в данный момент, через секунду уже никого не заинтересует. Например, предположим, что вы хотите написать программу для регистрации всех модулей, загруженных в сис­тему. Поскольку операционная система в любое время может прервать выполнение потока, отрабатывающего вашу программу, чтобы предоставить какие-то кванты времени другому потоку в системе, модули теоретически могут создаваться и разрушаться даже в момент выборки информации о них.

В этой динамической среде имело бы смысл на мгновение заморозить систему, чтобы получить такую системную информацию. В ToolHelp32 не предусмотрено средств замораживания системы, но есть функция, с помощью которой можно сделать "снимок" системы в заданный момент времени. Эта функция называется CreateToolhelp32Snapshot(), и ее объявление выглядит следующим образом:

function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle;

stdcall;

Параметр dwFlags означает тип информации, подлежащий включению в моментальный снимок. Этот параметр может иметь одно из перечисленных в табл. значений.

Значение

Описание

TH32CS_INHERIT

Означает, что дескриптор снимка будет наследуемым

TH32CS_SNAPALL

Эквивалентно заданию значений th32cs_snapheaplist, TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS и TH32CS_SNAPTHREAD

TH32CS_SNAPHEAPLIST

Включает в снимок список куч заданного процесса Win32

TH32CS_SNAPMODULE

Включает в снимок список модулей заданного процесса Win32

TH32CS_SNAPPROCESS

Включает в снимок список процессов Win32

TH32CS_SNAPTHREAD

Включает в снимок список потоков Win32

Функция CreateToolhelp32Snapshot() возвращает дескриптор созданного снимка или -1 в случае ошибки. Возвращаемый дескриптор работает подобно другим дескрипторам Win32 относительно процессов и потоков, для которых он действителен.

Следующий код создает дескриптор снимка, который содержит информацию обо всех процессах, загруженных в настоящий момент (EToolHelpError — это исключительная ситуация, определенная программистом):


var

Snap: THandle;

begin

Snap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if Snap = -1 then

raise EToolHelpError.Create('CreateToolHelp32Snapshot failed');

end;

Для освобождения связанных с ним ресурсов используйте функцию CloseHandle ().

Обработка информации о процессах

Имея дескриптор снимка, содержащий информацию о процессах, можно воспользоваться двумя функциями ТооlНе1р32, которые позволяют последовательно просмотреть сведения обо всех процессах в системе. Функции Process32First() и Process32Next() определены следующим образом:

function Process32First(hSnapshot: THandle; var lppe: TProcessEntry32):BOOL; stdcall;

function Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL; stdcall;

Первый параметр у обеих функций является дескриптором снимка, возвращаемым функцией CreateToolhelp32Snapshot().Второй параметр, lppe, представляет собой запись TProcessEntry32, которая передается по ссылке. По мере прохождения по элементам перечисления функции будут заполнять эту запись информацией о следующем процессе. Запись TProcessEntry32 определяется так:

type

TProcessEntry32 = record

dwSize: DWORD;

cntUsage: DWORD;

th32ProcessID: DWORD;

th32DefaultHeapID: DWORD;

th32ModuleID: DWORD;

cntThreads: DWORD;

th32ParentProcessID: DWORD;

pcPriClassBase: Longint;

dwFlags: DWORD;

szExeFile: array[0..MAX_PATH - 1] of Char;

end;

  • В поле dwSize содержится размер записи TProcessEntry32. До использования этой записи поле dwSize должно быть инициализировано значением SizeOf (TProcessEntry32).

  • В поле cntUsage хранится значение счетчика ссылок процесса. Когда это значение станет равным нулю, операционная система выгрузит процесс.

  • В поле th32ProcessID содержится идентификационный номер процесса.

  • Поле th32DefaultHeapID предназначено для хранения идентификатора (ID) для кучи процесса, действующей по умолчанию. Этот ID имеет значение только для функций Тоо1Не1р32, и его нельзя использовать с другими функциями Win32.

  • Поле thModulelD идентифицирует модуль, связанный с процессом. Это поле имеет значение только для функций TooIHelp32.

  • По значению поля cntThreads можно судить о том, сколько потоков начало выполняться в данном процессе.

  • Поле th32ParentProcessID идентифицирует родительский процесс для данного процесса.

  • В поле pcPriClassBase хранится базовый приоритет процесса. Операционная система использует это значение для управления работой потоков.

  • Поле dwFlags зарезервировано.

  • В поле szExeFile содержится строка с ограничивающим нуль-символом, которая представляет собой путь и имя файла ЕХЕ-программы или драйвера, связанного с данным процессом.

После создания снимка, содержащего информацию о процессах, для опроса данных по каждому процессу следует вызвать сначала функцию Process32First(), а затем вызывать функцию Process32Next() до тех пор, пока она не вернет значение False.

Обработка информации о потоках

Для составления списка потоков некоторого процесса в Тоо1Не1р32 предусмотрены две функции, которые аналогичны функциям, предназначенным для регистрации процессов: Thread32First() и Thread32Next(). Эти функции объявляются следующим образом:

function Thread32First(hSnapshot: THandle; var lpte: TThreadEntry32): BOOL; stdcall;


function Thread32Next(hSnapshot: THandle; var lpte: TThreadENtry32): BOOL; stdcall;

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

type

TThreadEntry32 = record

dwSize: DWORD;

cntUsage: DWORD;

th32ThreadID: DWORD;

th320wnerProcessID: DWORD;

tpBasePri: Longint;

tpDeltaPri: Longint;

dwFlags: DWORD;

end;

  • Поле dwSize определяет размер записи, и поэтому оно должно быть инициализировано значением SizeQf (TThreadEntry32) до использования этой записи.

  • В поле cntUsage содержится счетчик ссылок данного потока. При обнулении этого счетчика поток выгружается операционной системой.

  • Поле th32ThreadID представляет собой идентификационный номер потока, который имеет значение только для функций TooIHelp32.

  • В поле th32OwnerProcessID содержится идентификатор (ID) процесса, которому принадлежит данный поток. Этот ID можно использовать с другими функциями Win32.

  • Поле tpBasePri представляет собой базовый класс приоритета потока. Это значение одинаково для всех потоков данного процесса. Возможные значения этого поля обычно лежат в диапазоне от 4 до 24. Описания этих значений приведены в табл.

Допустимые значения класса приоритета потоков

значения

«пспспис

Описание

4

Ожидающий

8

Нормальный

13

Высокий

24

Реальное время

  • Поле tpDeltaPri представляет собой дельта-приоритет (разницу), определяющий величину отличия реального приоритета от значения tpBasePri. Это число со знаком, которое в сочетании с базовым классом приоритета отображает общий приоритет потока.

  • Поле dwFlags в данный момент зарезервировано и не должно использоваться.

Обработка информации о модулях

Опрос модулей выполняется практически так же, как опрос процессов или потоков. Для этого в Тоо1Не1р32 предусмотрены две функции: Module32First() и Module32Next(), кото­рые определяются следующим образом:

function Module32First(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; stdcall;

function Module32Next(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; stdcall;

Первым параметром в обеих функциях является дескриптор снимка, а вторым var-параметром — запись TModuleEntry32. Ее определение имеет следующий вид:

tуре

TModuleEntry32 = record

dwSize: DWORD;

th32ModuleID: DWORD;

th32ProcessID: DWORD;

GlblcntUsage: DWORD;

ProccntUsage: DWORD;

modBaseAddr: РВУТЕ;

modBaseSize: DWORD;

hModule: HMODULE;

szModule: array[0..MAX_MODULE_NAME32 + 1] of Char;

szExePath: array[0..MAX_PATH - 1] of Char;

end;

  • Поле dwSize определяет размер записи и поэтому должно быть инициализировано значением SizeOf (TModuleEntry32) до использования этой записи.

  • Поле th32ModuleID представляет собой идентификатор модуля, который имеет значение только для функций TooIHelp32.

  • Поле th32ProcessID содержит идентификатор (ID) опрашиваемого процесса. Этот ID можно использовать с другими функциями Win32.

  • Поле GlblcntUsage содержит глобальный счетчик ссылок данного модуля.

  • Поле ProccntUsage содержит счетчик ссылок модуля в контексте процесса-владельца.

  • Поле modBaseAddr представляет собой базовый адрес модуля в памяти. Это значение действительно только в контексте идентификатора процесса th32ProcessID.

  • Поле modBaseSize определяет размер (в байтах) модуля в памяти.

  • В поле hModule содержится дескриптор модуля. Это значение действительно только в контексте идентификатора процесса th32ProcessID.

  • В поле szModule содержится строка с именем модуля, завершающаяся нуль-символом.

  • Поле szExepath предназначено для хранения строки с ограничивающим нуль-символом, содержащей полный путь модуля.


Обработка информации о динамической памяти (кучах)

Опрос куч несколько сложнее опроса других типов объектов. В Тоо1Не1р32 предусмотрены четыре функции, с помощью которых можно получить информацию о кучах. Первые две, Heap32ListFirst() и Heap32ListNext(позволяют выполнить проход по всем кучам процесса, а две другие, Heap32First() и Heap32Next(), используются для получения более подробной информации обо всех блоках внутри отдельной кучи.

Функции Heap32ListFirst() и Heap32ListNext() определяются следующим образом:

function Heap32ListFirst(hSnapshot: THandle; var lphl: THeapList32): BOOL; stdcall;

function Heap32ListNext(hSnapshot: THandle; var lphl: THeapList32): BOOL; stdcall;

И вновь первый параметр является дескриптором снимка, а второй (lphl) представляет собой запись типа THeapList32, передаваемую по ссылке. Определение этой записи имеет следующий вид:

type

THeapList32 = record

dwSize: DWORD;

th32ProcessID: DWORD;

th32HeapID: DWORD;

dwFlags: DWORD;

end;

  • Поле dwSize определяет размер записи, и поэтому оно должно быть инициализировано значением SizeOf (THeapList32) до использования этой записи.

  • В поле th32ProcessID содержится идентификатор (ID) процесса-владельца.

  • В поле th32HeapID содержится идентификатор (ID) кучи. Этот ID имеет значение только для заданного процесса, и его можно использовать только с функциями Тоо1Не1р32.

  • В поле dwFlags хранится признак, который определяет тип кучи. В качестве значения этого поля может использоваться либо константа HF32 DEFAULT (которая означает, что текущая куча является стандартной кучей процесса), либо константа HF32_SHARED (которая означает, что текущая куча является разделяемой обычным способом).

Функции Heap32First() и Heap32Next() определяются следующим образом:

function Heap32First(var lphe: THeapEntry32; th32ProcessID, th32HeapID: DWORD): BOOL; stdcall;

function Heap32Next(var lphe: THeapEntry32): BOOL; stdcall;

Списки параметров этих функций немного отличаются от соответствующих списков функций, связанных с перечислением процессов, потоков, модулей. Эти функции предназначены для перечисления блоков данной кучи в данном процессе, а не некоторых свойств одного процесса, вызове функции Heap32First() параметры, установленные в полях th32ProcessID и ;32HeapID, должны быть равны значениям одноименных полей записи THeapList32, заполненной с помощью функций Heap32ListFirst() или Heap32ListNext(). Var-параметр lphe функций Heap32First() и Heap32Next() имеет тип THeapEntry32. Эта запись содержит дескриптивную информацию, относящуюся к блоку кучи, и ее определение имеет следующий вид:

type

THeapEntry32=record

dwSize: DWORD;

hHandle: THandle;//дескриптор этого блока кучи

dwAddress: DWORD;//линейный адрес начала блока

dwBlockSize: DWORD;//размер блока в байтах

dwFlags: DWORD;

dwLockCount: DWORD;

dwResvd: DWORD;

th32ProcessID: DWORD; // Процесс-владелец

th32HeapID: DWORD;// Идентификатор кучи в нем

end;

  • Поле dwSize определяет размер записи и поэтому должно быть инициализировано значением SizeOf (THeapEntry32) до использования этой записи.

  • В поле hHandle содержится дескриптор блока кучи.

  • Поле dwAddress представляет собой линейный адрес начала блока кучи.

  • В поле dwBlockSize содержится размер в байтах этого блока кучи.

  • В поле dwFlags хранится признак, который определяет тип блока кучи. Это поле может иметь одно из значений:


LF32_FIXED – блок памяти имеет фиксированное местонахождение

LF32_FREE – блок памяти не используется

LF32 MOVEABLE – блок памяти можно перемещать

  • Поле dwLockCount представляет собой счетчик блокировок блока памяти. Это значение увеличивается на единицу при каждом вызове процессом функции GlobalLock() или LосаlLоск().

  • Поле dwResvd зарезервировано в данный момент и не должно использоваться.

  • В поле th32ProcessID содержится идентификатор процесса-владельца.

  • Поле th32HeapID является идентификатором кучи, которой принадлежит блок.

Поскольку до составления списка блоков кучи вам придется сначала составить список куч, код опроса блоков кучи немного сложнее. В приведеннм ниже методе TDetailForra.WalkHeaps() вложены Heap32First()/Heap32Next() внутрь цикла Heap32ListFirst()/Heap32ListNext(). В этом методе вводится дополнительный уровень сложности путем добавления указателя на объекты типа записи PHeapEntry32 в ту часть массива DetailLists, которая относится к списку куч

procedure WalkHeaps;

{ Использует функции ToolHelp32 для составления списка куч }

var

HL: THeapList32;

НЕ: THeapEntry32;

РНЕ: PHeapEntry32;

begin

DetailLists[ltHeap].Clear;

HL.dwSize := SizeOf(HL);

HE.dwSize:=SizeOf(HE);

If Heap32ListFirst(FCurSnap, HL) then

repeat

if Heap32First(HE, HL.th32ProcessID, HL.th32HeapID) then

repeat

{ Необходимо создать копию записи THeapList32, что позволит

сохранить информацию для просмотра сведений о куче позднее}

New(РНЕ);

РНЕ^ := НЕ;

DetailLists[ltHeap].AddObject(Format(SHeapStr, [HL.th32HeapID, Pointer(HE.dwAddress), HE.dwBlockSize, GetHeapFlagString(HE.dwFlags) ]), TObject(PHE));

until not Heap32Next(HE);

until not Heap32ListNext(FCurSnap, HL);

HeapListAlloc := True;

end;