Изоляция пакета драйвера
Изоляция пакетов драйверов — это требование для драйверов Windows , которое делает пакеты драйверов более устойчивыми к внешним изменениям, проще обновлять и проще устанавливать.
Примечание
Хотя для драйверов Windows требуется изоляция пакета драйверов, драйверы классических приложений Windows по-прежнему получают преимущества благодаря повышению устойчивости и удобства обслуживания.
В следующей таблице приведены некоторые примеры устаревших методов использования пакетов драйверов, которые больше не разрешены для драйверов Windows в левом столбце, а также требуемое поведение для драйверов Windows в правом столбце.
Неизолированные драйверы | Изолированный драйвер |
---|---|
INF копирует файлы в папку %windir%\System32 или %windir%\System32\drivers | Файлы драйверов запускаются из хранилища драйверов |
Взаимодействует со стеками устройств и драйверами с помощью жестко заданных путей | Взаимодействует со стеками устройств и драйверами с помощью системных функций или интерфейсов устройств |
Путь жесткого кода к расположениям глобального реестра | Использует HKR и системные функции для относительного расположения реестра и состояния файла |
Запись файла среды выполнения в любое расположение | Файлы записываются относительно расположений, предоставляемых операционной системой |
Справку по определению соответствия пакета драйверов требованиям к изоляции пакета драйверов см. в разделе Проверка драйверов Windows. Примеры обновления INF в соответствии с требованиями к изоляции пакета драйверов см. в разделе Перенос INF для соблюдения изоляции пакета драйвера.
Запуск из хранилища драйверов
Все изолированные пакеты драйверов оставляют файлы пакетов драйверов в хранилище драйверов. Это означает, что они указывают DIRID 13 в своем INF-файле, чтобы указать расположение файлов пакета драйверов при установке. Дополнительные сведения о том, как использовать его в пакете драйверов, см. в разделе Запуск из хранилища драйверов.
Состояние чтения и записи
Примечание
Если компонент использует свойства устройства или интерфейса устройства для хранения состояния, продолжайте использовать этот метод и соответствующие API ОС для хранения состояния и доступа к ней. Следующие рекомендации по состоянию реестра и файла предназначены для других состояний, которые должны храниться компонентом.
Доступ к различным состояниям реестра и файла должен осуществляться путем вызова функций, которые предоставляют вызывающей объекту расположение состояния, а затем состояние считывается или записывается относительно этого расположения. Не используйте жестко закодированные абсолютные пути реестра и пути к файлам.
В этом разделе содержатся следующие подразделы:
Состояние реестра
В этом разделе содержатся следующие подразделы:
Состояние реестра устройств PnP
Изолированные пакеты драйверов и компоненты пользовательского режима обычно используют одно из двух расположений для хранения состояния устройства в реестре. Это аппаратный ключ (ключ устройства) для устройства и программный ключ (ключ драйвера) для устройства. Ключ оборудования обычно предназначен для параметров, связанных с взаимодействием отдельного экземпляра устройства с оборудованием. Например, чтобы включить аппаратную функцию или перевести оборудование в определенный режим. Программный ключ обычно предназначен для параметров, связанных с взаимодействием отдельного экземпляра устройства с системой и другим программным обеспечением. Например, для настройки расположения файла данных, взаимодействия с платформой или доступа к параметрам приложения для устройства. Чтобы получить дескриптор в этих расположениях реестра, используйте один из следующих вариантов:
IoOpenDeviceRegistryKey (WDM)
CM_Open_DevNode_Key (код в пользовательском режиме)
Директива INF AddReg с использованием корневых записей HKR в разделе надстройки реестра , на который ссылается раздел INF DDInstall или DDInstall.HW , как показано ниже:
[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg
[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll
Состояние реестра интерфейса устройства
Для чтения и записи состояния реестра интерфейса устройства используйте один из следующих вариантов:
CM_Open_Device_Interface_Key (код в пользовательском режиме)
Директива INF AddReg с использованием записей reg-root HKR в разделе add-registry-section, на который ссылается раздел add-interface-section
Состояние реестра служб
Состояние службы следует классифицировать по одной из трех категорий
Состояние реестра неизменяемых служб
Неизменяемое состояние службы — это состояние, предоставляемое пакетом драйвера, устанавливающим службу. Эти значения реестра, заданные inf для драйверов и служб Win32, должны храниться в подразделе "Параметры" службы, указав строку HKR в разделе AddReg , а затем сослаться на этот раздел в разделе установки службы в INF. Пример:
[ExampleDDInstall.Services]
Addservice = ExampleService, 0x2, Example_Service_Inst
[Example_Service_Inst]
DisplayName = %ExampleService.SvcDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %13%\ExampleService.sys
AddReg=Example_Service_Inst.AddReg
[Example_Service_Inst.AddReg]
HKR, Parameters, ExampleValue, 0x00010001, 1
Чтобы получить доступ к расположению этого состояния из службы во время выполнения, используйте одну из следующих функций:
IoOpenDriverRegistryKey (WDM) с DRIVER_REGKEY_TYPE DriverRegKeyParameters
GetServiceRegistryStateKey (службы Win32) с SERVICE_REGISTRY_STATE_TYPE ServiceRegistryStateParameters
Эти значения реестра, предоставленные inf в подразделе "Параметры" для службы, должны быть считываться только во время выполнения и не изменяться. Они должны рассматриваться только для чтения.
Если значения реестра, предоставляемые INF, являются параметрами по умолчанию, которые могут быть перезаписаны во время выполнения, значения переопределения должны быть записаны в состояние внутреннего реестра службы или состояние общего реестра служб для службы. При получении параметров можно сначала найти параметр в изменяемом состоянии. Если он не существует, параметр можно искать в неизменяемом состоянии. RtlQueryRegistryValueWithFallback можно использовать для выполнения запросов к таким параметрам, которые имеют переопределение и значение по умолчанию.
Состояние внутреннего реестра служб
Внутреннее состояние службы — это состояние, которое записывается во время выполнения и принадлежит и управляется только самой службой и доступно только для этой службы. Чтобы получить доступ к расположению для внутреннего состояния службы, используйте одну из следующих функций из службы:
IoOpenDriverRegistryKey (WDM) с DRIVER_REGKEY_TYPE DriverRegKeyPersistentState
GetServiceRegistryStateKey (службы Win32) с SERVICE_REGISTRY_STATE_TYPE ServiceRegistryStatePersistent
Если служба хочет разрешить другим компонентам изменять эти параметры, служба должна предоставить интерфейс, который может вызвать другой компонент, который сообщает службе, как изменить эти параметры. Например, служба Win32 может предоставлять интерфейс COM или RPC, а служба драйверов — интерфейс IOCTL через интерфейс устройства.
Состояние реестра общих служб
Состояние общей службы — это состояние, которое записывается во время выполнения и может использоваться совместно с другими компонентами пользовательского режима, если они имеют достаточные привилегии. Чтобы получить доступ к расположению для этого общего состояния службы, используйте одну из следующих функций:
IoOpenDriverRegistryKey (WDM) с DRIVER_REGKEY_TYPE DriverRegKeySharedPersistentState
GetSharedServiceRegistryStateKey (службы Win32) с SERVICE_SHARED_REGISTRY_STATE_TYPE ServiceSharedRegistryPersistentState
Состояние файла
В этом разделе содержатся следующие подразделы:
Состояние файла устройства
Если файлы, связанные с устройством, необходимо записывать во время выполнения, эти файлы должны храниться относительно дескриптора или пути к файлу, предоставленному через API ОС. Файлы конфигурации, относящиеся к данному устройству, являются одним из примеров того, какие типы файлов будут храниться здесь. Чтобы получить доступ к расположению этого состояния, используйте одну из следующих функций из службы:
IoGetDeviceDirectory (WDM) с параметром DirectoryType , равным DeviceDirectoryData
Состояние файла службы
Состояние файла службы можно разделить на одну из трех категорий.
Состояние неизменяемого файла службы
Состояние неизменяемого файла службы — это файлы, которые являются частью пакета драйвера. Дополнительные сведения о доступе к этим файлам см. в статье Запуск из хранилища драйверов.
Состояние внутреннего файла службы
Внутреннее состояние файла службы — это состояние, которое записывается во время выполнения и принадлежит и управляется только самой службой и доступно только этой службе. Чтобы получить доступ к расположению для внутреннего состояния службы, используйте одну из следующих функций из службы:
IoGetDriverDirectory (WDM, KMDF) с параметром DirectoryType , равным DriverDirectoryData
GetServiceDirectory (службы Win32) с параметром eDirectoryType , равным ServiceDirectoryPersistentState
Если служба хочет разрешить другим компонентам изменять эти параметры, служба должна предоставить интерфейс, который может вызвать другой компонент, который сообщает службе, как изменить эти параметры. Например, служба Win32 может предоставлять интерфейс COM или RPC, а служба драйверов — интерфейс IOCTL через интерфейс устройства.
Состояние файла общей службы
Состояние файла общей службы — это состояние, которое записывается во время выполнения и может использоваться совместно с другими компонентами пользовательского режима, если они имеют достаточные привилегии. Чтобы получить доступ к расположению для этого общего состояния службы, используйте одну из следующих функций:
IoGetDriverDirectory (WDM, KMDF) с параметром DirectoryType , равным DriverDirectorySharedData
GetSharedServiceDirectory (службы Win32) с параметром DirectoryType , равным ServiceSharedDirectoryPersistentState
DriverData и ProgramData
Файлы, к которым можно предоставить общий доступ с другими компонентами, но которые не вписываются в категорию состояния файлов общей службы , можно записать в DriverData
расположения или ProgramData
.
Эти расположения предлагают компонентам расположение для записи временного состояния или состояния, которое предназначено для использования другими компонентами и потенциально собирается и копируется из системы для обработки другой системой. Например, пользовательские файлы журналов или аварийные дампы соответствуют этому описанию.
Избегайте записи файлов в корне каталогов DriverData
или ProgramData
. Вместо этого создайте подкаталог с названием вашей компании, а затем запишите файлы и другие подкаталоги в этом каталоге.
Например, для названия компании Contoso драйвер в режиме ядра может записывать пользовательский журнал в \DriverData\Contoso\Logs
, а приложение в пользовательском режиме может собирать или анализировать файлы журналов из %DriverData%\Contoso\Logs
.
DriverData
Каталог DriverData
доступен в Windows 10 версии 1803 и более поздних версий и доступен администраторам и драйверам UMDF.
Драйверы в режиме ядра обращаются к каталогу DriverData
с помощью предоставленной системой символьной ссылки с именем \DriverData
.
Программы пользовательского режима обращаются к каталогу DriverData
с помощью переменной %DriverData%
среды .
ProgramData
Переменная %ProgramData%
среды пользовательского режима доступна для компонентов пользовательского режима для использования при хранении данных.
Временные файлы
Временные файлы обычно используются в промежуточных операциях. Их можно записать в вложенный путь в переменных %TEMP%
среды или %TMP%
. Так как доступ к этим расположениям осуществляется через переменные среды, эта возможность ограничена компонентами пользовательского режима. После закрытия дескрипторов для этих временных файлов нет никаких гарантий на время существования или сохранение этих временных файлов. Операционная система или пользователь могут удалить их в любое время, и они могут не сохраняться при перезагрузке.
Избегайте записи файлов в корне каталогов %TEMP%
или %TMP%
. Вместо этого создайте подкаталог с названием вашей компании, а затем запишите файлы и другие подкаталоги в этом каталоге.
Состояние свойства
Устройства и интерфейсы устройств поддерживают хранение состояния с помощью модели свойств PnP. Модель свойств позволяет хранить структурированные данные свойств на устройстве или в интерфейсе устройства. Это предназначено для небольших данных, которые достаточно вписываются в типы свойств, поддерживаемые моделью свойств.
Для доступа к свойствам устройства можно использовать следующие API:
Драйверы WDM
Драйверы WDF
Код пользовательского режима
Для доступа к свойствам интерфейса устройства можно использовать следующие API:
Драйверы WDM
Драйверы WDF
Код пользовательского режима
Использование интерфейсов устройств
Если драйвер хочет разрешить другим компонентам считывать или изменять внутреннее состояние драйвера, драйвер должен предоставить интерфейс, который может вызвать другой компонент, который сообщает драйверу, какие параметры следует вернуть или как изменить определенные параметры. Например, служба драйверов может предоставлять интерфейс IOCTL через интерфейс устройства.
Как правило, драйвер, которому принадлежит состояние, предоставляет интерфейс устройства в пользовательском классе интерфейса устройства. Когда драйвер будет готов к доступу к состоянию другими компонентами, он включает интерфейс . Чтобы получать уведомления о включении интерфейса устройства, компоненты пользовательского режима могут регистрировать уведомления о поступлении интерфейса устройства , а компоненты режима ядра могут использовать IoRegisterPlugPlayNotification. Чтобы эти компоненты могли получить доступ к состоянию, драйвер, включающий интерфейс, должен определить контракт для своего класса пользовательского интерфейса устройства. Этот контракт обычно имеет один из двух видов:
Контракт ввода-вывода можно связать с этим классом интерфейса устройства, который предоставляет механизм доступа к состоянию. Другие компоненты используют включенный интерфейс устройства для отправки запросов ввода-вывода, соответствующих контракту.
Интерфейс прямого вызова, возвращаемый через интерфейс запроса. Другие драйверы могут отправлять IRP_MN_QUERY_INTERFACE для получения указателей функций из вызываемого драйвера.
Кроме того, если драйвер, владеющий состоянием, разрешает прямой доступ к состоянию, другие драйверы могут получить доступ к состоянию с помощью системных функций для программного доступа к состоянию интерфейса устройства. Дополнительные сведения см. в разделе Состояние реестра интерфейса устройства .
Эти интерфейсы или состояние (в зависимости от используемого метода совместного использования) должны иметь правильную версию, чтобы драйвер, владеющий состоянием, можно было обслуживать независимо от других компонентов, которые обращаются к такому состоянию. Поставщики драйверов не могут полагаться на то, что другие компоненты обслуживаются одновременно с драйвером и остаются в той же версии.
Так как устройства и драйверы, управляющие интерфейсами, приходят и уходят, драйверы и приложения должны избегать вызова IoGetDeviceInterfaces при запуске компонента, чтобы получить список включенных интерфейсов. Вместо этого рекомендуется зарегистрироваться для получения уведомлений о поступлении или удалении интерфейса устройства, а затем вызвать соответствующую функцию, чтобы получить список существующих включенных интерфейсов на компьютере.
Дополнительные сведения об интерфейсах устройств см. в разделе:
Регистрация для получения уведомлений о получении и удалении интерфейса устройства
Регистрация для уведомления об изменении интерфейса устройства
Краткий справочник по поддержке API управления состоянием в операционной системе
Большинство пакетов драйверов должны поддерживать ряд версий операционной системы. Дополнительные сведения о том, как достичь этого в пакете драйверов, см. в разделе Поддержка нескольких версий операционных систем . В следующих таблицах приведены краткие сведения о том, когда была добавлена поддержка операционной системы для различных API управления состоянием.
Драйверы WDM
Операционная система | Добавлена поддержка |
---|---|
Windows 2000 |
IoOpenDeviceRegistryKey IoOpenDeviceInterfaceRegistryKey |
Windows Vista |
IoGetDevicePropertyData IoSetDevicePropertyData |
Windows 8 |
IoGetDeviceInterfacePropertyData IoSetDeviceInterfacePropertyData |
Windows 8.1 | IoQueryFullDriverPath |
Windows 10 1803 |
IoOpenDriverRegistryKey для RegKeyTypedriverRegKeyParameters и DriverRegKeyPersistentState IoGetDeviceDirectory IoGetDriverDirectory для DirectoryTypedriverDirectoryImage и DriverDirectoryData |
Windows 10, 1809 | RtlQueryRegistryValueWithFallback |
Windows 11 21H2 |
IoOpenDriverRegistryKey для RegKeyTypedriverRegKeySharedPersistentState IoGetDriverDirectory for DirectoryTypeof DriverDirectorySharedData |
Драйверы KMDF
Драйверы UMDF
Код пользовательского режима
Операционная система | Добавлена поддержка |
---|---|
Windows 2000 | CM_Open_DevNode_Key |
Windows Vista |
CM_Open_Device_Interface_Key CM_Get_DevNode_Property CM_Set_DevNode_Property CM_Get_Device_Interface_Property CM_Set_Device_Interface_Property |
Windows 10 2004 |
GetServiceRegistryStateKey GetServiceDirectory |
Windows 11 21H2 |
GetSharedServiceRegistryStateKey GetSharedServiceDirectory |