Класс KDevice является суперклассом для всех классов устройств. Но на практике он сейчас почти не используется. Чаще используют его потомка – класс KPnpDevice. Этот класс предназначен для управления PnP-устройствами, т.е. устройствами, которые конфигурируется системой. В данный момент практически все устройства являются PnP-устройствами. Появление таких устройств здорово облегчило жизнь разработчикам драйверов: использовать KPnpDevice намного проще, а часто и безопаснее, чем KDevice. Еще бы, ведь в данном случае все проблемы конфигурирования и инициализации ресурсов оборудования ложатся на широкие плечи системы.
Любой объект устройства содержит стандартные методы обработки запросов на чтение, запись и управление устройством (device control). Эти методы вызываются при вызове соответствующих функций API ReadFile(), WriteFile(), DeviceControl().
Каждый драйвер содержит минимум один объект устройства. Как было упомянуто выше, объект устройства является экземпляром класса, порожденного программистом от класса KDevice или KPnpDevice. Для придания функциональности объекту устройства разработчик драйвера может переопределять виртуальные методы суперкласса, включая те методы, которые обрабатывают различные типы IRP, а также добавлять свои свойства и методы в класс. В процессе разработки можно использовать как иерархию классов DriverStudio, так и функции DDK. Впрочем, для большинства задач без использования DDK вполне можно обойтись.
Естественно, делать все это надо с осторожностью. Вызов некотроых методов является обязательным. Переопределение виртуальных методов также требует осторожности: многие из них содержат код, который обязательно должен быть выполнен. Если его удалить, то драйвер будет работать неправильно (если будет работать вообще). В результате, система скорее всего, зависнет.
Все вышесказанное, конечно, может быть очень интересным, но остается открытым вопрос: так как же все-таки драйвер, вернее объект устройства, управляет аппаратурой? Официально провозглашается, что Win2000 — переносимая система. Т.е., если она хорошо работает на архитектуре Intel, то она также может быть перенесена и на другие системы, например Alpha. Для того, чтобы система с минимальными исправлениями могла работать на компьютерах с другой архитектурой, и был введен HAL — уровень абстракции аппаратуры. Он действительно абстрагирует драйвера и большую часть кода ядра ОС от того, как именно построен компьютер. Теперь разработчику драйвера становится абсолютно все равно, как на данном компьютере реализован контроллер прерываний или контроллер прямого доступа к памяти – все ресурсы аппаратуры также представлены объектами. Это диапазоны адресов памяти и портов В/В устройства, линии прерываний и ПДП. Все они могут быть реализованы в различных архитектурах по разному, но общие принципы их работы остаются одними и теми же. Соответственно, и интерфейс классов, реализующих управление этими ресурсами, остается одинаковым. Нам, как программистам, теперь не нужно знать тонкости работы аппаратной части на этом компьютере — это задача HAL и тех людей, которые переносили систему.