Унифицированная модель драйвера
Имя устройства и символическая связь
При создании объекта-устройства также может быть указано его имя, которое будет видимо в директории "\Device" пространства имен диспетчера объектов. Объекты – устройства используются в Windows NT как точки входа в пространства имен, не контролируемые менеджером объектов. Если при разборе имени объекта диспетчер объектов встречает объект-устройство, то он вызывает метод разбора, связанный с этим устройством.
Если имя не указано, объект-устройство может быть использован только внутри драйвера и недоступен извне. Если быть более точным, такой объект-устройство можно использовать, если иметь указатель на описывающую его структуру.
Именованный объект-устройство доступен для использования через вызов системного сервиса NtCreateFile().
Для обращения к именованному объекту-устройству из подсистемы Win32 посредством функции CreateFile() должны быть предприняты дополнительные действия. Функция CreateFile() ищет имя устройства в директории Диспетчера Объектов "\??" (NT 4.0 и Win2000), либо "\DosDevices"(NT 3.51). Поэтому в соответствующей директории, а для большей совместимости это должна быть "\DosDevices", должен быть создан объект (символическая связь), указывающий на имя устройства в директории "\Device". Обычно связь создается в самом драйвере, хотя это можно сделать и из прикладной программы пользовательского режима с помощью Win32 – функции DefmeDosDevice().
Взаимосвязь основных объектов
Что происходит при успешном открытии объекта-устройства (неважно, с помощью какой функции: CreateFile() или NtCreateFile()? Для описания состояния работы с каждым объектом, открытым с помощью этих функций, создается новый экземпляр объекта-файла. Именно отсюда название функции – CreateFile.
С точки зрения прикладного уровня ОС функции открытия файла могут применяться для открытия файлов, устройств, именованных каналов, почтовых слотов и т.п. Однако, с точки зрения ядра ОС, объекта-файла (в смысле файл на жестком Диске) не существует, как не существует объектов именованный канал или почтовый слот. В действительности объект-файл будет связан с некоторым объектом-устройством, для которого имеет смысл, допустим, понятие "файл" (в смысле файл файловой системы).
Соответственно, каждая операция ввода/вывода на прикладном уровне будет производиться с некоторым объектом-файлом. Причем конкретный объект будет указан не напрямую, а через так называемый описатель (HANDLE), возвращаемый как результат работы функции CreateFile().
Важно отметить, что каждый процесс имеет свою собственную таблицу описателей, обеспечивая уникальность описателей только в рамках своей таблицы. Это означает, например, что для двух процессов – А и В – описателю со значением 1 будут в общем случае соответствовать два различных объекта-файла (см. рис. 8). Кроме того, ОС поддерживает механизм наследования описателей. В этом случае два разных процесса через два разных описателя будут разделять один и тот же объект-файл.
Рис. 8. Описателю со значением 1 соответствуют два различных объекта-файла
Практически уникальность описателя только в контексте данного процесса означает невозможность использования описателя драйвером при работе в случайном контексте. Описатель обязательно должен быть переведен в указатель на объект посредством вызова функции диспетчера объектов ObReferenceObjectBy-Handle().