Windows tool help library

Библиотека Tool Help для Windows 2000/9х

Продолжая рассказ о программных интерфейсах Windows NT/2000, в этой статье я остановлюсь на небольшой, но интересной библиотеке Tool Help Library (далее THL).

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

THL — один из таких интерфейсов. Данная библиотека позволяет получить информацию о состоянии работающих на локальном компьютере приложений. Вообще говоря, библиотека предназначена для написания всякого рода отладчиков, но, я думаю, область ее применения на самом деле заметно шире. Описанная технология не работает на Windows NT, только на Windows 2000, 95/98/Me. Демонстрационная программа, исходные тексты которой находятся по адресу: http://members.xoom.com/alex_ep/source/th.zip , транслировалась в Microsoft Visual C++ 6.0 SP5 и тестировалась под управлением Windows 2000 Professional SP1.

Снимки системы

В основе THL лежит понятие «snapshot» — мгновенного снимка состояния запущенных приложений. Перед вызовом всех функций библиотеки необходимо создать snapshot. Это осуществляется вызовом функции

Параметр dwFlags указывает, какая именно информация интересует пользователя. Его значения приведены в Таблице 1.

Параметр th32ProcessID идентифицирует процесс, состояние которого исследуется. Он необходим при использовании dwFlags со значениями TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE и TH32CS_SNAP-THREAD. В остальных случаях этот параметр игнорируется.

Так, например, для получения списка модулей процесса dwProcessID необходим следующий вызов:

Уничтожается объект snapshot стандартным вызовом CloseHandle( hSnapshot );

Все ошибки, возникающие при выполнении функций THL, возвращаются стандартным вызовом GetLast-Error и FormatMesssage.

Список процессов

Чтобы получить список действующих в настоящий момент процессов, необходимо написать код, пример которого приведен в Листинге 1.

В примере используются две функции:

В обеих функциях два параметра. Первый — дескриптор, возвращаемый предыдущим вызовом CreateToolhelp-32Snapshot, а второй указывает на структуру PROCESSENTRY32, в которой возвращается результат выполнения функции. Перед вызовом Process32First необходимо установить в поле dwSize структуры PROCES-SENTRY32 значение, равное размеру самой структуры — sizeof(PROCES-SENTRY32), иначе функция вернет ошибку.

Список модулей, загруженных процессом

В процессе работы практически любого приложения Win32 загружаются те или иные библиотеки, компоненты и другие программные модули. Естественно, возникает желание получить список загруженных модулей. Для этого в THL также предусмотрен простой механизм. В Листинге 2 приведен фрагмент кода, иллюстрирующий решение этой задачи.

В нем, в первую очередь, вызывается CreateToolhelp32Snapshot с параметрами TH32CS_SNAPMODULE и идентификатором процесса, модули которого нас интересуют. Далее, как и в предыдущем примере, в поле dwSize, но теперь уже структуры MODULEENTRY32, устанавливается значение, равное ее размеру. Кстати, это необходимо делать для всех функций перечисления THL.

Цикл перебора ничем не отличается от рассмотренного в предыдущем примере. Разве что он использует структуру MODULEENTRY32, в которую возвращается информация о модуле. Описание полей этой структуры содержится в Таблице 2.

Потоки процесса

Механизм работы с потоками процесса идентичен механизму, описанному для модулей, только вызываются функции Thread32First и Thread32Next, а вместо структуры MODULEENTRY32 используется THREADENTRY32.

Доступ к памяти процесса

Известно, что в Win32 получить доступ к памяти одного процесса из другого невозможно. Тем не менее в THL есть функция, позволяющая получить копию блока памяти другого процесса:

Читайте также:  Джойстик defender scorpion rs3 драйвер windows 10

Параметры у этой замечательной функции следующие:

[in] Идентификатор процесса, блок памяти которого необходимо скопировать. Если этот параметр равен нулю, то копируется память из текущего процесса.

[in] Адрес в адресном пространстве указанного процесса, начиная с которого копируется информация. Перед выполнением операционная система проверяет, вся ли указанная память доступна для чтения. Если это не так, возвращается FALSE.

[out] Указатель на буфер, в который должны быть скопированы данные.

[in] Размер буфера в байтах.

[out] Количество скопированных байтов.

А как узнать, где в адресном пространстве процесса находятся данные? В самом общем случае на этот вопрос ответить невозможно. Но для динамически распределяемой памяти (heap) THL предоставляет функции, эту проблему решающие.

Исследование динамической памяти процесса

Для выделения области в виртуальной памяти используется функция HeapCreate, которая создает соответствующий объект (heap) в адресном пространстве процесса. Для выделения памяти внутри этого блока используется функция HeapAlloc. Все остальные функции работы с динамической памятью (GlobalAlloc, malloc, calloc и т. д.) сводятся к использованию этого механизма, который мы не будем здесь подробно рассматривать.

Очевидно, что нужно уметь находить список выделенных областей виртуальной памяти и для каждого из них — список выделенных блоков. Посмотрим, как это делается с помощью функций THL (см. Листинг 3). В терминах THL область памяти называется heap, множество областей памяти — heap list, а выделенному внутри нее блоку соответствует термин «block of a heap».

Первый цикл с помощью функций Heap32ListFirst и Heap32ListNext возвращает список блоков памяти, которые были распределены. Зная идентификатор процесса и идентификатор области виртуальной памяти, который возвращается в поле th32HeapID структуры HEAPLIST32, можно просмотреть, как распределяется память внутри этого блока. Выделенные области памяти можно получить с помощью функций Heap32First и Heap32-Next. Они возвращают структуру HEAPENTRY32, описание полей которой приведено в Таблице 3.

Зная значения полей dwAddress и dwBlockSize, с помощью функции Toolhelp32ReadProcessMemory нетрудно получить данные, находящиеся в динамической памяти процесса.

В заключение остается добавить, что информацию о Tool Help Library можно найти в MSDN по адресу: http://msdn.microsoft.com/library/ psdk/helplib/toolhelp_5pfd.htm .

Александр ЭПШТЕЙН — руководитель отдела разработки компании Internet Investment Group. С ним можно связаться по адресу: alex_ep@hotmail.com.

Таблица 1. Значения параметра dwFlags-функции. CreateToolhelp32Snapshot.

TH32CS_INHERIT показывает, что snapshot был унаследован.
TH32CS_SNAPHEAPLIST получает список блоков динамически распределенной памяти в адресном пространстве процесса.
TH32CS_SNAPMODULE получает список модулей, загруженных процессом.
TH32CS_SNAPPROCESS получает список запущенных на локальном компьютере процессов.
TH32CS_SNAPTHREAD получает список потоков процесса.
TH32CS_SNAPALL включает в себя предыдущие четыре флага, т. е. snapshot будет содержать списки процессов, потоков, модулей и областей динамической памяти.

Таблица 2. Описание полей структуры MODULEENTRY32.

DWORD dwSize размер структуры в байтах
DWORD th32ModuleID ID модуля
DWORD th32ProcessID ID процесса модуля
DWORD GlblcntUsage общее для системы количество обращений к модулю
DWORD ProccntUsage количество обращений к модулю, сделанных из текущего процесса
BYTE * modBaseAddr адрес модуля в адресном пространстве процесса
DWORD modBaseSize размер модуля
HMODULE hModule дескриптор модуля в контексте процесса
TCHAR szModule [MAX_MODULE_NAME32 + 1] имя модуля
TCHAR szExePath[MAX_PATH] полный путь к файлу

Таблица 3. Описание полей структуры HEAPENTRY32.

SIZE_T dwSize размер структуры HEAPENTRY32 в байтах.
HANDLE hHandle дескриптор блока памяти в адресном пространстве процесса.
ULONG_PTR dwAddress адрес начала блока памяти.
SIZE_T dwBlockSize размер блока памяти.;
DWORD dwFlags флаги, описывающие область памяти. Этот параметр может принимать следующие значения:
LF32_FIXED область памяти не может быть перемещена операционной системой;
LF32_FREE блок памяти не используется;
LF32_MOVEABLE область памяти выделена и может перемещаться.
DWORD dwLockCount количество вызовов функции GlobalLock (в Win32 LocalLock синоним функции GlobalLock), которые были сделаны для этого блока памяти.
DWORD dwResvd зарезервировано.
DWORD th32ProcessID ID процесса, в контексте которого выделена память.
ULONG_PTR th32HeapID идентификатор блока памяти, выделенного функцией HeapCreate.

Поделитесь материалом с коллегами и друзьями

codexpert blog

I see native code

Listing Processes – Part 3: Using Tool Help Library

Tool Help Library makes it easy to enumerate and get info about processes, threads, modules, and heaps. Let’s use it to get a list of running processes.

Using Tool Help Library

First, take a snapshot by passing TH32CS_SNAPPROCESS flag to CreateToolhelp32Snapshot function. Next, pass the snapshot handle to Process32First, then to Process32Next to get running processes info in a list of PROCESSENTRY32 structures.

Next example fills a listview control with the following info of each process.

    • PID (process identifier);
    • process image name (the name of the executable file);
    • parent PID;
    • number of threads started by the process;
    • base priority of any threads created by this process.

Demo project

The demo project is a simple MFC dialog-based application that uses the above functions.
Download: Listing_Processes_Using_Tool_Help_Library.zip (973)

Using Tool Help Library – Demo Application

Resources

See also

  • Codexpert blog: Listing Processes – Part 1: Introduction
  • Codexpert blog: Listing Processes – Part 2: Using PSAPI
  • Codexpert blog: Listing Processes – Part 4: Using Remote Desktop Services API

Share this:

Like this:

About Ovidiu Cucu

Co-founder CODEXPERT Follow me on Twitter: https://twitter.com/ovidiucucu

3 thoughts on “ Listing Processes – Part 3: Using Tool Help Library ”

You can the same process info with commandline ps commands:
:

$ ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 00:33 ? 00:00:00 /sbin/init
root 2 0 2 0 1 00:33 ? 00:00:00 [kthreadd]
root 3 2 3 0 1 00:33 ? 00:00:00 [ksoftirqd/0]

Where PPID is the Parent process of the PID and LWP gives the thread id of each thread. NLWP is the number of threads in the system for the underlying process. And, lot more process info with ps command options. Just see man ps and the web for examples of each.

$ ps -eo uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args

USER PID PPID NLWP %CPU %MEM PSR START TT TIME COMMAND
root 1 0 1 0.0 0.1 0 00:33 ? 00:00:00 /sbin/init
root 2 0 1 0.0 0.0 0 00:33 ? 00:00:00 [kthreadd]
root 3 2 1 0.0 0.0 0 00:33 ? 00:00:00 [ksoftirqd/0]

CreateToolhelp32Snapshot function (tlhelp32.h)

Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes.

Syntax

Parameters

The portions of the system to be included in the snapshot. This parameter can be one or more of the following values.

Value Meaning
TH32CS_INHERIT 0x80000000 Indicates that the snapshot handle is to be inheritable.
TH32CS_SNAPALL Includes all processes and threads in the system, plus the heaps and modules of the process specified in th32ProcessID. Equivalent to specifying the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, and TH32CS_SNAPTHREAD values combined using an OR operation (‘|’).
TH32CS_SNAPHEAPLIST 0x00000001 Includes all heaps of the process specified in th32ProcessID in the snapshot. To enumerate the heaps, see Heap32ListFirst.
TH32CS_SNAPMODULE 0x00000008 Includes all modules of the process specified in th32ProcessID in the snapshot. To enumerate the modules, see Module32First. If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds.

64-bit Windows:В В Using this flag in a 32-bit process includes the 32-bit modules of the process specified in th32ProcessID, while using it in a 64-bit process includes the 64-bit modules. To include the 32-bit modules of the process specified in th32ProcessID from a 64-bit process, use the TH32CS_SNAPMODULE32 flag.

TH32CS_SNAPMODULE32 0x00000010 Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process. This flag can be combined with TH32CS_SNAPMODULE or TH32CS_SNAPALL. If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds.
TH32CS_SNAPPROCESS 0x00000002 Includes all processes in the system in the snapshot. To enumerate the processes, see Process32First.
TH32CS_SNAPTHREAD 0x00000004 Includes all threads in the system in the snapshot. To enumerate the threads, see Thread32First.

To identify the threads that belong to a specific process, compare its process identifier to the th32OwnerProcessID member of the THREADENTRY32 structure when enumerating the threads.

The process identifier of the process to be included in the snapshot. This parameter can be zero to indicate the current process. This parameter is used when the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPMODULE32, or TH32CS_SNAPALL value is specified. Otherwise, it is ignored and all processes are included in the snapshot.

If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from opening them.

If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).

Return value

If the function succeeds, it returns an open handle to the specified snapshot.

If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError. Possible error codes include ERROR_BAD_LENGTH.

Remarks

The snapshot taken by this function is examined by the other tool help functions to provide their results. Access to the snapshot is read only. The snapshot handle acts as an object handle and is subject to the same rules regarding which processes and threads it is valid in.

To enumerate the heap or module states for all processes, specify TH32CS_SNAPALL and set th32ProcessID to zero. Then, for each additional process in the snapshot, call CreateToolhelp32Snapshot again, specifying its process identifier and the TH32CS_SNAPHEAPLIST or TH32_SNAPMODULE value.

When taking snapshots that include heaps and modules for a process other than the current process, the CreateToolhelp32Snapshot function can fail or return incorrect information for a variety of reasons. For example, if the loader data table in the target process is corrupted or not initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, the function might fail with ERROR_BAD_LENGTH or other error code. Ensure that the target process was not started in a suspended state, and try calling the function again. If the function fails with ERROR_BAD_LENGTH when called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the function again until it succeeds.

The TH32CS_SNAPMODULE and TH32CS_SNAPMODULE32 flags do not retrieve handles for modules that were loaded with the LOAD_LIBRARY_AS_DATAFILE or similar flags. For more information, see LoadLibraryEx.

To destroy the snapshot, use the CloseHandle function.

Note that you can use the QueryFullProcessImageName function to retrieve the full name of an executable image for both 32- and 64-bit processes from a 32-bit process.

Читайте также:  Подключение заблокировано вследствие превышения лимита времени teamviewer linux
Оцените статью