Использование NuMega DriverStudio для написания WDM-драйверов - [14]
Итак, для установки драйвера в системе предполагается наличие в системе PCI — карточки XDSP-680. После установки карточки (или перепрограммирования ее из среды Foundation) следует перезагрузить компьютер. При загрузке компьютер обнаружит новое устройство и потребует предоставить драйвер для него. Если же не потребует — значит в системе есть более ранняя версия драйвера. Для этого надо открыть список устройств, установленных на компьютере и обновить драйвер для устройства. Для этого надо указать путь к скрипту xdsp.inf и к файлу драйвера xdsp.sys.
Если же Вы разрабатываете драйвер, который не управляет каким-либо устройством или это устройство не является PnP — необходимо просто установить драйвер стандартными средствами Windows: Пуск→Настройка→Панель управления→Установка оборудования. Когда Windows выведет полный список типов устройств и спросит, какое устройство Вы хотите установить, выберите свой тип устройства.
Если разработанный Вами драйвер не подходит под какой-либо из известных классов устройств, то "Другие устройства" также являются неплохим вариантом. Такая ситуация тоже случается нередко — мне, например, приходилось разрабатывать драйвер для программатора микроконтроллеров, подключавшегося через параллельный порт. Конечно же, он не подходил под какой-либо из известных в Windows типов устройств.
После того, как драйвер будет установлен, нужно будет проверить его функционирование. Запустите скомпилированный файл test_xdsp.exe с параметрами test_xdsp r 32 (команда прочитать 32 байта из устройства). Должно появиться сообщение, похожее на это:
>C:\XDSP\exe\objchk\i386>Test_XDSP.exe r 32
>Test application Test_XDSP starting…
>Device found, handle open.
>Reading from device – 0 bytes read from device (32 requested).
>–, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –, –,
>–, –, –, –, –, –,
В данном случае приложение установило связь с драйвером и прочитало из него 32 байта. Функция чтения в драйвере не определена, поэтому, естественно, драйвер вернет абракадабру. Если же будет получено сообщение вида
>C:\…Projects\XDSPdrv\exe\objchk\i386>Test_XDSP.exe r 32
>Test application Test_XDSP starting…
>ERROR opening device: (2) returned from CreateFile
>Exiting…
— то приложение не смогло установить связь с драйвером. Следует попробовать переустановить драйвер.
2.3 Наращивание функциональных возможностей драйвера.
Рассмотрим подробно текст драйвера, сгенерированного DriverWizard и внесем в него необходимые изменения.
В проекте пристствуют всего два класса:
XDSP
класс драйвера;
XDSPDevice
класс устройства.
Также есть несколько глобальных функций и переменных:
PNPMinorFunctionName — возвращает строку с текстовым названием кода функции IOCTL. Эта функция используется при отладке, когда надо перевести числовое значение кода IOCTL в строку с его названием.
POOLTAG DefaultPoolTag('PSDX') — используется совместно с BoundsChecker для отслеживания возможных переполнений буфера и утечек памяти.
KTrace t("XDSPdrv") — глобальный объект трассировки драйвера. Этот объект используется для вывода сообщений трассировки при работе драйвера. Использование объекта трассировки аналогично использованию класса iostream в С++. Вывод отладочных сообщений производится при помощи оператора <<. Примеры использования объекта трассировки неоднократно встречаются в тексте драйвера, например:
>t << "m_bBreakOnEntry loaded from registry, resulting value: [" << m_bBreakOnEntry << "]\n";
В данном примере объект трассировки используется для вывода строки "m_bBreakOnEntry loaded from registry, resulting value: [" и значения логической переменной m_bBreakOnEntry. Все сообщения трассировки можно прочитать в отладчике SoftIce.
Начнем анализ текста драйвера с класса XDSP (класс драйвера). В строке 31 при помощи макроса DECLARE_DRIVER_CLASS декларируется класс драйвера XDSP. Далее следует метод DriverEntry, который вызывается при инициализации драйвера:
>NTSTATUS XDSPdrv::DriverEntry(PUNICODE_STRING RegistryPath)
>//В строке RegistryPath содержится ключ реестра, в котором система хранит информацию о драйвере.
>{
> //Далее выводится трассировочное сообщение, информирующее о вызове метода DriverEntry:
> t << "In DriverEntry\n";
> //После этого драйвер создает объект Params класса KRegistryKey и считывает данные из
> //реестра для этого драйвера:
> KRegistryKey Params(RegistryPath, L"Parameters");
> //Далее производится проверка на успех:
> if ( NT_SUCCESS(Params.LastError()) ) {
> //Текст, заключенный в макрос препроцессора DBG будет откомпилирован только в отладочной версии
> //драйвера.
>#if DBG
> ULONG bBreakOnEntry = FALSE;
> // Читается значение переменной BreakOnEntry реестра:
> Params.QueryValue(L"BreakOnEntry", &bBreakOnEntry);
> // Если она принимает значение true,то инициировать точку останова в отладчике.
> if (bBreakOnEntry) DbgBreakPoint();
>#endif
> //Загрузить остальные параметры реестра.
> LoadRegistryParameters(Params);
> }
> m_Unit = 0;
> //Вернуть успех
> return STATUS_SUCCESS;
>}
Метод LoadRegistryParameters зaгружает из реестра все остальные параметры, необходимые для драйвера. Впрочем, в нашем драйвере таковых нет, и поэтому функция не выполняет никаких полезных действий (просто загружает значение переменной m_bBreakOnEntry).