Автор работы: Пользователь скрыл имя, 04 Января 2011 в 19:53, курсовая работа
Разработкой драйверов обычно занимаются профессионалы, каждая крупная компания, выпускающая технику имеет целый штат сотрудников, занимающихся разработкой драйверов. Прежде всего, разработчик драйвера должен владеть программированием на языке С (без расширений С++), поскольку описание синтаксиса и применения конструкций этого языка не рассматриваются в данной книге вовсе. Во-вторых, разработчик драйверов, пусть начинающий, должен иметь твердо сформировавшееся представление о программировании в многозадачной среде при интенсивном использовании многопоточности.
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID MapRegisterBase,
IN PVOID Context
};
IO_ALLOCATION_ACTION
ControllerControl{
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID MapRegisterBase,
IN PVOID Context
};
Клавиатура,
мышь, последовательный, параллельный,
звуковой драйверы и драйвер файловой
системы имеют процедуру
VOID Cancel{
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
};
Любой драйвер верхнего уровня, который создает запросы к более низкоуровневым драйверам, должен иметь, по крайней мере, одну процедуру IOComlpetion для освобождения всех структур IRP, созданных драйвером. Таким образом, любой драйвер высшего уровня должен иметь процедуру IOComlpetion. Другие процедуры драйвера могут сказать, чтобы IOComlpetion была вызвана, когда все низкоуровневые драйвера обработают текущий запрос.
NTSTATUS
IOComlpetion{
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
};
Для отслеживания времени, занимаемого процедурой ввода/вывода, или для некоторой другой цели, определяемой разработчиком, любой драйвер должен иметь процедуры IoTimer и/или CustomTimerDpc. IoTimer вызывается раз в секунду, когда драйвер включает таймер. Вторая же может быть вызвана в более мелкий или переменный интервал.
VOID
CustomTimerDpc{
IN struct_KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
};
Драйвер
должен иметь процедуру Unload, если
он может быть выгружен во время работы
системы.
VOID
XxxUnload{
IN PDRIVER_OBJECT DriverObject
};
Для
осуществления обращений к
Функции IoCreateDevice создает новый объект устройства и инициализирует его для использования драйвером. Объект устройства представляет собой физическое, виртуальное или логическое устройство, которое необходимо драйверу для поддержки динамического управления этим устройством.
NTSTATUS
IoCreateDevice{
IN PDRIVER_OBJECT DriverObject, // указатель на объект драйвера
IN ULONG DeviceExtensionSize, // размер блока пользовательской
IN PUNICODE_STRING DeviceName,// имя устройства (иногда опускаются)
IN DEVICE_TYPE DeviceType, // тип устройства (последовательное,
// диск, мышь и т.п.)
IN ULONG DeviceCharacteristics, // параметры устройства
// (вынимаемое и пр.)
IN BOOLEAN Exclusive, // параллельность доступа к устр.
OUT PDEVICE_OBJECT *DeviceObject // указатель на объект
};
Функция IOCreateSymbolicLink создает символическую ссылку между устройством и видимым пользователем именем.
NTSTATUS
IOCreateSymbolicLink{
IN PUNICODE_STRING SymbolicLinkName, // символическое имя,
// видимое пользователем
IN PUNICODE_STRING DeviceName // имя устройства
// в пространстве имен Windows
};
Функция IoCompleteRequest объявляет менеджеру ввода/вывода, что обработка текущего запроса ввода/вывода закончена.
VOID
ioCompleteRequest{
IN PIRP Irp, // указатель на запрос ввода/вывода
IN CCHAR PriorityBoost // повышение приоритета драйвера для обработки
// запроса. Зависит от обрабатываемого устройства.
// IO_NO_INCREMENT при ошибке или очень быстрой обработке запроса
};
Часть 5. Драйвер для принтера
5.1. Архитектура печати в Windows
Самые главные компоненты этой архитектуры – это принтерный спулер и набор драйверов принтеров.
Спулер – это компонент архитектуры Windows, являющийся сервером печати, работающим с очередями печати. Он имеет клиент-серверную архитектуру.
К клиенту относятся:
- приложение, которому нужны услуги печати или какие-либо, связанные с ними, которые может ему предоставить спулер; все запросы приложение отправляет к GDI (это нижестоящий компонент)
- Winspool.drv – пользовательский интерфейс, предоставляемый спулером. Этот компонент находится еще ниже. Все компоненты в этом списке перечисляются от вышестоящих к нижестоящим.
Серверные компоненты:
- Spoolsv.exe – API-сервер спулера
- Spoolss.dll – это «роутер» спулера. Он разбирает поступающие к нему запросы и определяет, к какому провайдеру их нужно переадресовать.
Самый важный компонент – это провайдер печати – компонент, работающий с определенными для него локальными и удаленными устройствами печати. Также через провайдер печати можно производить различные действия с очередями печати.
Провайдеры печати бывают следующих типов:
- провайдер локальной печати; файл – localspl.dll
- провайдер сетевой печати; файл – win32spl.dll
- провайдер печати Novell NetWare; файл – win32spl.dll
- провайдер печати, работающий с HTTP; файл – inetpp.dll
Провайдер локальной печати.
Основное его назначение – управлять всеми ресурсами в системе, связанными с печатью:
- очередями печати
- драйвером принтера
- заданиями принтера
- портами
Все функции, определенные провайдером печати, делятся на:
- функции инициализации
- функции управления драйвером принтера, очередями печати, заданиями принтера, портами, реестром и т.д.
Кроме того, есть еще функция XcvData, обеспечивающая связь между серверной и клиентской DLL - библиотеками монитора порта.
Локальный провайдер печати, помимо поддержки стандартного набора функций, также должен поддерживать:
- архитектура драйвера принтера вместе в вызовами к DLL-библиотеке интерфейса локального принтера.
- архитектуру предоставляемого производителем процессора печати
- архитектуру предоставляемого производителем монитора порта
5.2 Драйвера принтеров
Существует
несколько типов драйверов
Процесс создания универсального драйвера модно разбить на три компонента и реализовывать их отдельно:
- плагин для Microsoft Render
- мини-драйвер принтера
- монитор порта
Мини-драйвер принтера отвечает за предоставление информации о принтере для механизма рендеринга. Рендер перехватывает задания принтера, формирует из них растровые строки, а затем уже передает их спулеру. Информация о принтере ему нужна для того, чтобы корректно обработать задания принтера. Мини-драйвер принтера создается при помощи утилиты Unitool, входящей в состав DDK. Благодаря ей данные GPC (General Printer Charecterization) для одного или нескольких схожих растровых принтеров будут определены и организованы в мини-драйвере.
Плагин для Microsoft Render: существует зарегистрированная функция IPrintOemUni::FilterGraphics, которая получает доступ к сформированным растровым строкам перед их отправкой спулеру. Это дает возможность модифицировать строки перед отправкой: зашифровать, сжать и т.д.
Монитор порта (port monitor) – это часть архитектуры подсистемы печати Windows. Каждый монитор порта поддерживает стандартный набор API-функций. Спулер вызывает все эти функции по мере надобности.
LPMONITOREX
InitializePrintMonitor (LPWSTR pRegistryRoot);
Спулер вызывает эту функцию во время инициализации и получает от нее структуру, содержащую точки входа для остальных функций. У монитора порта есть только две точки точки входа. Одна из них находится в этой функции, а другая – в функции DllEntryPoint. Монитор порта экспортирует все функции в структуре, полученной спулером. Эта функция вызывается спулером в момент загрузки им монитора порта посредством функции Win32 API LoadLibrary. В остальных случаях играет роль точки входа для спулера для загрузки DLL-библиотеки в память и больше ничего не делает.
Спулер вызывает функцию OpenPort в момент назначения порта принтеру. Эта функция возвращает дескриптор порта в pName. Спулер использует возвращенный функцией дескриптор в последующих вызовах монитора порта: StartDocPort, WritePort, ReadPort и EndDocPort. Спулер ожидает завершения функции OpenPort (успеха или неудачи)приемлемое время. Все процедуры инициализации, которые может иметь монитор порта, выполняются в этой функции.
Обычно вызывает ClosePort, когда порту, указанному параметром hPort, больше не соответствует ни одного принтера.
Спулер вызывает функцию StartDocPort, когда он готов к отсылке задания на принтер.
Функция WritePort посылает данные, указанные в pBuffer, принтеру. Спулер вызывает эту функцию, если ему необходимо отослать полное задание на принтер. Спулер устанавливает размер блока в параметре cbBuf. Если от принтера нет отклика, WritePort будет ждать приемлемое время и, не получив ответа, вернет FALSE. Функция WritePort всегда должна проинициализировать pcbWritten нулем перед попыткой записи в порт. Если попытка записи в порт оказалась успешной, то в pcbWritten будет находиться число посланных байтов.
Функция ReadPort поддерживает принтеры, обеспечивающие двунаправленный обмен информацией. Если принтер ничего не предает, то ReadPort выждет положенное время, чтобы окончательно убедиться в отсутствии поступающих от принтера данных, и вернет FALSE. Функция ReadPort всегда должна проинициализировать pcbRead нулем перед попыткой принятия данных от принтера. Если чтение данных, принятых от принтера, оказалось успешным, то pcbRead будет содержать число переданных байтов.