Курсовая работа: Профилировщик приложений
Выходные данные : структура с базовой информацие о процессе.
Эта пара IOCTL-запросов позволяет их инициатору последовательно проссматривать структуры, описывающие запущенные процессы в системе. Каждый из них вызывает одноимённую функцию ProcessFirst() и ProcessNext() соответственно. Первая функция устанавливает указатель на первую запись, а вторая перемещает указатель на следующую, если такая имеется. Результатом выполнения каждой из этих функций является заполненная структура с информацией оп процессе, если не достигнут конец списка. В том случае, когда конец списка всё-таки достигается, IRP-пакет, тем не менее, помечается как успешно обработанный, но значение количества переданных байтов устанавливается равным нулю, что и позволяет пользовательскому приложению правильно распознать такую ситуацию и своевременно прекратить посылать драйверу дальнейшие IOCTL_PROCESS_NEXT-запросы.
3.1.4.5 IOCTL_THREAD_FIRST и IOCTL_THREAD_NEXT. Входные данные : [нет]
Выходные данные : структура с базовой информацие о потоке.
Как и в предыдущем пункте, эта пара IOCTL-запросов позволяет их инициатору последовательно проссматривать структуры, описывающие потоки выбранного процесса. Логика обработки этих запросов аналогична получению информации о процессах.
3.1.4.6 IOCTL_OPEN_THREAD . Входные данные : права доступа, уникальный идентификатор целевого потока.
Выходные данные : описатель целевого потока.
При обработке данного IOCTL-запроса осуществляется попытка открыть описатель потока, имеющего указанный идентификатор с правами, которые были запрошены пользовательским приложением-клиентом.
3.1.4.6 IOCTL_CLOSE_THREAD . Входные данные : описатель целевого потока.
Выходные данные : [нет].
Во время обработки этого IOCTL-запроса предпринимается попытка закрыть описатель потока, открытый ранее с помощью IOCTL_OPEN_THREAD-запроса.
3.1.4.7 IOCTL_GET_THREAD_CONTEXT . Входные данные : структура аппаратного контекста, описатель целевого потока.
Выходные данные : структура аппаратного контекста.
Этот IOCTL-запрос наиболее полно использует возможности API-вызова DeviceIoControl, так как здесь задействованы оба, входной и выходной, буферы. На вход поступает структура для аппаратного контекста с инициализированным полемы CONTEXT::ContextFlags, указывающим какие группы регистров аппаратного контекста должны быть возвращены в этой структуре при удачном завершении запроса. В этом проекте запрашивается весь аппаратный контекст.
3.2 Пользовательское приложение
Пользовательское приложение включает в себя два класса: CDialog и CDriver. Как понятно из названий эти классы отвечают соответственно за взаимодействие с пользователем через диалоговое окно приложения и взаимодействие с драйвером преимущественно через IOCTL-запросы.
При запуске экземпляр пользовательского приложения первым делом пытается установить драйвер, в том случае, если это не было сделано ранее другим экземпляром. Если установка вызвала ошибку, то пользователю выдаётся соответствующее сообщение, в котором в текстовом виде указывается причина её возникновения, если она была предусмотрена, иначе – просто указывается её код. Пользователь может запросить установку драйвера ещё раз, дав положительный ответ на соответствующее предложение программы. Такая процедура повторятся до тех пор, пока установка драйвера не пройдёт успешно либо пользователь откажется от повторной попытки.
После этого загружается ниспадающий список запущенных процессов, отсортированных в алфавитном порядке по своим именам, выбирается первый процесс из списка, и уже его потоки отображаются во втором ниспадающем списке. Эти списки обновляются каждый раз, когда пользователь хочет выбрать другой процесс или поток, так как для этого ему нужны последние сведения.
Далее создаётся таймер, работа которого никак не связана с работой таймера драйвера. Этот таймер отвечает за периодичный вывод полученной от драйвера информации на форму диалога.
Эта информация получается через драйвера, как уже говорилось, с помощью API-вызова DeviceIoControl:
BOOL DeviceIoControl
(HANDLE ,
DWORD ,
LPVOID , DWORD ,
LPVOID , DWORD ,
LPDWORD ,
LPOVERLAPPED );
HANDLE – описатель устройства, которому посылается запрос;
DWORD – код IOCTL-запроса;
LPVOID – адрес входного буфера;