Используемые инструментальные программы
Запуск драйверов выполнялся при помощи программы Monitor (из пакета Numega Driver Studio) после полной загрузки операционной системы. Этот простой способ запуск драйверов позволяет проследить все диагностические сообщения всех рабочих процедур испытываемых драйверов, начиная от DriverEntry и заканчивая процедурой DriverUnload.
Сборка драйвера выполнялась в отладочной среде Win 2K Checked Build Environment, что уже стало традицией для примеров данной книги. Драйвер собирался как Legacy Driver при помощи определений ntddk.h и простейшего файла Sources:
TARGETNAME=LPTPort
TARGETTYPE=DRIVER TARGETPATH=.
INCLUDES= $(BASEDIR)\inc;. SOURCES=driver.cpp
Компиляция драйверов как Legacy Driver обеспечила отсутствие проблем при старте и остановке драйверов программой Monitor. Программный код драйверов размещен в двух файлах Driver.cpp (собственно исполняемые процедуры) и Driver.h (заголовочный файл). Для двух вариантов драйверов, работающих с прерываниями, которые описываются в данной главе, исходные тексты приводятся ниже полностью по причине необходимости большого количества дополнительных комментариев.
Поскольку драйверы компилировались в отладочной среде DDK, это позволило выводить отладочную диагностику при помощи условно компилируемых фрагментов вида:
#if DBG==1 DbgPrint( "LPTPORT: Interrupt %d converted to kIrql = %d, " "kAffinity = %d, kVector = %X(hex)\n", pDevExt->Irq, kIrql, kAffinity, kVector); #endif
Сбор диагностики выполнялся программой DebugView, которая всегда запускалась до старта драйвера из программы Monitor. Это позволило собирать отладочные сообщения всех драйверных процедур, включая диагностику из DriverEntry.
При работе с объектом события во втором варианте драйвера привлекалась программа WinObj, которая подтвердила создание именованного объекта события "BaseNamedObjects\LPTPORT_EVENT" в соответствующей ситуации.
Кроме того, при отсутствии документированного описания должного уровня детализации на функцию IoCreateSynchronizationEvent во всех версиях DDK (включая примеры) было предпринято дизассемблирование некоторых системных драйверов при помощи дизассемблера IDA. Это позволило установить причину отказа данной функции от нормального завершения при вызовах с целью создания именованного объекта события в драйвере и правильно выполнить ее вызов.
Для интерпретации ошибок по их коду использовалась программа ErrLook, описанная ранее.