В соответствии с идеологией DriverWorks драйвер представляется, как набор объектов. Эта же идея присутствует и в "чистой" архитектуре WDM, но DriverWorks упорядочивает эти объекты и представляет их экземплярами классов. Классы DriverWorks также несколько упрощают код драйвера по сравнению с DDK, делают его более компактным и доступным для понимания. Часто повторяющиеся, рутинные фрагменты кода драйвера спрятаны внутри методов класса. И то, что при использовании пакета DDK занимало несколько строк в программе, теперь можно вполне заменить вызовом одного единственного метода.
Также в DriverWorks предложено несколько полезных классов: например класс KFile — доступ к файлам или классы динамических списков и массивов.
В общем, сама идея DriverWorks напоминает Visual C++ и библиотеку MFC. MFC представляет из себя некую прослойку, которая отделяет программиста от жутковатых функций API и позволяет создавать объектно-ориентированные проекты, при этом оставаясь на достаточно низком уровне программирования.
Впрочем, в системе классов DriverWorks есть одна особенность: иерархия классов практически отсутствует. Это вполне естественно: в системе классов DriverWorks присутствуют самые различные классы — классы, представляющие собой ресурсы устройства (линии ПДП, прерываний, областей памяти, портов ввода-вывода), сами устройства, классы для взаимодействия с реестром, файлами и т.п. Еще одним аргументом в пользу отсутствия наследования является то, что разветвленная иерархия классов может снизить быстродействие программы. Для драйвера, это, конечно, неприемлемо.
В основе архитектуры DriverWorks лежит несколько основных классов.
Объект драйвера является экземпляром класса KDriver. Он представляет драйвер в целом как некую абстракцию. Для объекта драйвера абсолютно все равно, каким оборудованием он управляет, объект драйвера об этом по настоящему никогда не задумывается. Его задача — обеспечить интерфейс драйвера с ОС: загрузка и инициализация драйвера, выгрузка и т.п. А управление аппаратурой возлагается на другие объекты драйвера, в частности, на объект устройства.
Когда ОС загружает драйвер, то она создает для него соответствующий объект драйвера. Компонент ядра операционной системы — диспетчер ввода-вывода (I/O Manager) — использует объекты драйверов для управления устройствами. Каждый драйвер отвечает за управление одним или несколькими объектами устройств. Запрос на операцию ввода-вывода (I/O request), посланный приложением пользователя, поступает к диспетчеру ввода-вывода.
Диспетчер ввода-вывода определяет, какой именно объект драйвера отвечает за соответствующий объект устройства, и перенаправляет ему запрос. Кроме управления объектами устройств, объект драйвера имеет дополнительные методы, отвечающие за инициализацию и завершение работы драйвера. Программист создает свой подкласс класса KDriver для взаимодействия с системой. Он обязательно должен содержать метод DriverEntry — функцию, вызываемую при инициализации драйвера.
В отличие от обычного не-WDM драйвера, процедура инициализации WDM-драйвера выполняет весьма ограниченное число функций: в основном это загрузка некоторых внутренних переменных на основе данных реестра. WDM-драйвер не инициализирует ресурсы устройства при старте в вызове EntryPoint. Для этого существует объект устройства.
WDM-драйвер экспортирует метод AddDevice, который вызывается системой, если обнаружено устройство, поддерживаемое данным драйвером. Этот метод отвечает за создание объектов устройств, соответствующих системным физическим объектам устройств (Physical Device Object, PDO).
Объект драйвера может содержать дополнительные методы для реинициализации драйвера на более поздних стадиях загрузки системы. Такой подход необходим, если в системе присутствует несколько драйверов, критичных к порядку их загрузки. Впрочем, такие проблемы встречаются нечасто.
В принципе, хорошо спроектированный драйвер должен экспортировать метод Unload, который вызывается при выгрузке драйвера. Но такие случаи встречаются довольно редко.
Как было упомянуто выше, драйвер обращается к системному реестру при инициализации. Системный реестр (registry) — системная база данных, организованная в виде дерева, похожего на дерево каталогов. Каждую ветвь этого дерева (реестра) называют разделом (key), каждый лист – параметром (value). Данные, хранящиеся в реестре, могут быть разных типов: целое (integer), строка, набор байтов.
Система позволяет каждому драйверу хранить данные в реестре. Эти данные используются драйверами при старте и инициализации. Обычно драйвер хранит данные в разделе HKLM\SYSTEM\CurrentControlSet\Services\<имя драйвера>\Parameters\.