NTSTATUS XDSPdrvDevice::DeviceControl(KIrp I) {
NTSTATUS status;
t << "Entering XDSPdrvDevice::Device Control, " << I << EOL;
switch (I.IoctlCode()) {
case XDSPDRV_IOCTL_GETMEMSIZE:
//Получен определенный нами IOCTL-код XDSPDRV_IOCTL_GETMEMSIZE.
//Вызвать соответствующий обработчик.
status = XDSPDRV_IOCTL_GETMEMSIZE_Handler(I);
break;
default:
//Этот код не определен.
status = STATUS_INVALID_PARAMETER;
break;
}
if (status == STATUS_PENDING)
// Если драйвер по каким-то причинам отложил обработку запроса, переменной status
//присваивается значение STATUS_PENDING. Этот код будет возвращен методом
//DeviceControl.
{
return status;
} else
//В противном случае завершаем обработку пакета.
{
return I.PnpComplete(this, status);
}
}
Метод XDSPDRV_IOCTL_GETMEMSIZE_Handler является обработчиком IOCTL–кода XDSPDRV_IOCTL_GETMEMSIZE. Получив этот код, драйвер возвращает общий объем памяти устройтсва. Шаблон метода сгенерирован DriverWizard, но программист должен написать практически весь его код.
NTSTATUS XDSPdrvDevice::XDSPDRV_IOCTL_GETMEMSIZE_Handler(KIrp I) {
NTSTATUS status = STATUS_SUCCESS;
t << "Entering XDSPdrvDevice::XDSPDRV_IOCTL_GETMEMSIZE_Handler, " << I << EOL;
//Количество памяти будет возвращено как число unsigned long. Поэтому определяем
//указатель на unsigned long.
unsigned long *buf;
//Получаем указатель на буфер пользователя
buf=(unsigned long*) I.UserBuffer();
//Записываем туда количество памяти нашего устройства. Получаем его при помощи
//метода Count объекта m_MainMem.
*buf=m_MainMem.Count();
//Длина возвращаемых нами данных равна длине числа unsigned long.
I.Information() = sizeof(unsigned long);
//Возвращаем STATUS_SUCCESS
return status;
}
Написание драйвера завершено. Возможно, у Вас сложилось впечатление, что DriverWizard может практически все и написание драйвера — очень простая задача. Но не следует забывать, что наш драйвер — всего-то простейшая демонстрационная программа, которая практически не выполняет никаких полезных действий. Написание реальных драйверов является гораздо более сложной задачей.
Если бы драйвер был написан с использованием пакета DDK, то он бы имел практически ту же структуру и почти тот же код (правда, не объектно-ориентированный). Но в таком случае весь драйвер пришлось бы писать вручную, а DriverWizard генерирует скелет драйвера автоматически. Это сильно облегчает процесс разработки драйвера, позволяя программисту не заботиться о написании скелета драйвера и предохраняя его от возможных ошибок.
2.4 Разработка dll-библиотеки для взаимодействия с драйвером
dll-библиотека (Dynamic Link Library) — программный модуль, который может быть динамически подключен к выполняющемуся процессу. Dll–библиотека может содержать функции и данные. При подключении dll к процессу она отображается на адресное пространство этого процесса.
Если говорить по русски, то это означает: в любой момент времени программа может загрузить dll-библиотеку, получить указатели на функции и данные этой библиотеки. Потом приложение как-то использует функции и данные библиотеки, и когда они больше не нужны — выгружает библиотеку.
Dll-библиотека содержит два вида функций: внешние (External) и внутренние (Internal). Внутренние функции могут вызываться только самой dll, а внешние может также вызывать приложение, подключившее библиотеку. В этом случае говорят, что dll-библиотека экспортирует функции и данные.
Как было упомянуть выше, в настоящее время для связи с драйвером используется схема Приложение→Библиотека dll→Драйвер. При использовании такой архитектуры запрос приложения на операцию ввода-вывода поступает в dll-библиотеку, проходит там предварительную обработку и передается драйверу. Результат, возвращенный драйвером библиотеке dll, также обрабатывается и передается приложению. Преимущества такого подхода очевидны:
• Выпускается огромное количество различных периферийных устройств, и, соответственно, для каждого устройства разрабатывается свой драйвер. Программисту будет тяжело разбираться во всех тонкостях работы драйвера устройства: формат данных для чтения/записи, запоминать непонятные IOCTL-коды. Гораздо лучше — предоставить для него понятный интерфейс API-функций для работы с устройством. Еще лучше, если такой интерфейс будет унифицированным для всех устройств данного типа. Задача dll-библиотеки, поставляемой с драйвером – связать стандартные интерфейсы, предоставляемые прикладной программе, со специфическими алгоритмами работы драйвера.
Читать дальше