Поделиться через


Объявление функций с помощью типов ролей функций для драйверов WDM

Примечание.

Начиная с Windows 10 версии 2004 , средство проверки статических драйверов (SDV) больше не требует заметок для определения типов подпрограмм отправки для драйверов WDM. Следуйте инструкциям в разделе "Базовые и расширенные инициализации" этой страницы .

Чтобы уведомить SDV о точках входа драйвера при анализе драйвера WDM, вы должны объявить функции, используя объявления типов ролей функций. Типы ролей функции определяются в Wdm.h. Каждая точка входа в подпрограмме DriverEntry в драйвере WDM должна быть объявлена путем указания соответствующего типа роли. Типы ролей представляют собой стандартные типдефы, соответствующие распознаваемым точкам входа в драйвере WDM.

Например, чтобы создать объявление типа роли функции для подпрограммы выгрузки драйвера, называемой CsampUnload, используйте предопределённое объявление роли типа DRIVER_UNLOAD. Объявление типа роли функции должно отображаться перед определением функции.

DRIVER_UNLOAD CsampUnload;

Определение функции CsampUnload остается неизменным:

VOID
CsampUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    ...
}

SDV распознает типы точек входа, показанных в следующей таблице.

Тип роли функции WDM Подпрограмма WDM

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

ВЫГРУЗКА_ДРАЙВЕРА

выгрузки

DRIVER_ADD_DEVICE

AddDevice

Dispatch_type(тип) DRIVER_DISPATCH

Подпрограммы диспетчера, используемые драйвером. См. статью "Написание подпрограмм отправки".

IO_COMPLETION_ROUTINE

IoCompletion

Подпрограмма IoCompletion устанавливается путем вызова IoSetCompletionRoutine или IoSetCompletionRoutineEx и передачи указателя функции в подпрограмму IoCompletion в качестве второго параметра.

ОТМЕНА_ДРАЙВЕРА

Отмена

Подпрограмма Cancel устанавливается путем вызова функции IoSetCancelRoutine и передачи указателя на эту подпрограмму для отмены IRP в качестве второго параметра функции.

IO_DPC_ROUTINE

DpcForIsr

Подпрограмма DpcForIsr регистрируется путем вызова IoInitializeDpcRequest и передачи указателя функции в подпрограмму DpcForIsr в качестве второго параметра. Чтобы поставить DPC в очередь, вызовите IoQueueDpc в подпрограмме ISR, используя тот же объект DPC.

Отложенная_рутинная_процедура

CustomDpc

Подпрограмма CustomDpc задается путем вызова KeInitializeDpc и передачи указателя функции в CustomDpc в качестве второго параметра. Чтобы поставить CustomDpc в очередь для драйвера, вызовите KeInsertQueueDpc из ISR-подпрограммы, используя тот же DPC-объект.

KSERVICE_ROUTINE

Прерывание службы

Подпрограмма InterruptService (ISR) обслуживает прерывание устройства и при необходимости планирует обработку полученных данных после прерывания.

Запрос энергии завершен

Подпрограмма обратного вызова PowerCompletion завершает обработку power IRP. Если данному драйверу необходимо выполнить дополнительные задачи после того, как все другие драйверы завершили обработку IRP, он регистрирует подпрограмму обратного вызова PowerCompletion во время вызова подпрограммы PoRequestPowerIrp, которая выделяет IRP.

WORKER_THREAD_ROUTINE

Рутина

Подпрограмма — это подпрограмма обратного вызова, указанная во втором параметре функции ExInitializeWorkItem.

Подпрограмму следует объявлять таким образом, только если драйвер вызывает ExQueueWorkItem для добавления рабочего элемента в системную очередь.

Объявление процедур диспетчеризации драйверов

Начиная с Windows 10 версии 2004, объявления типов ролей функций для подпрограмм диспетчеризации автоматически уточняются с учетом их категории IRP на основе инициализации таблицы MajorFunction DriverObject в процедуре DriverEntry драйвера WDM.

Драйвер Foo должен выполнять объявления ролей с помощью базового или расширенного стиля объявления, чтобы соответствовать SDV.

Базовые и расширенные инициализации

Базовый стиль можно увидеть в приведенном ниже примере (обратите внимание, что имена подпрограмм диспетчера FooCreate и FooCleanup являются лишь примерами, можно использовать любое соответствующее имя):

DriverObject->MajorFunction[IRP_MJ_CREATE] = FooCreate; //Basic style
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCleanup;

Более сложный подход можно использовать для сокращения необходимого списка. Хотя одна и та же подпрограмма отправки используется для нескольких категорий IRP, драйвер может кодировать два инициализации таким образом:

DriverObject->MajorFunction[IRP_MJ_CREATE] = 
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCreateCleanup; // Advanced style for a multi-role dispatch routine 

Чтобы драйвер мог правильно запускать SDV, драйвер должен использовать только базовый или расширенный стиль, показанный выше. Проверка SDV на драйвере не будет работать должным образом , если один из этих двух методов не используется.

Параметры функции и типы ролей функций

По мере необходимости в языке программирования C типы параметров, используемые в определении функции, должны соответствовать типам параметров прототипа функции или в данном случае типу роли функции. SDV зависит от подписей функции для анализа и игнорирует функции, подписи которых не совпадают.

Например, следует объявить процедуру IoCompletion с помощью типа роли функции IO_COMPLETION_ROUTINE:

IO_COMPLETION_ROUTINE myCompletionRoutine;

При реализации myCompletionRoutine типы параметров должны соответствовать типам, используемым IO_COMPLETION_ROUTINE, а именно, PDEVICE_OBJECT, ПИРП и PVOID (см. подпрограмму IoCompletion для синтаксиса).

NTSTATUS
myCompletionRoutine(
 PDEVICE_OBJECT  DeviceObject,
 PIRP  Irp,
 PVOID  Context
 )
{
}

Выполнение анализа кода драйверов с целью проверки объявлений функций

Чтобы определить, подготовлен ли исходный код, запустите анализ кода для драйверов. Анализ кода для драйверов проверяет объявления типов ролей функции и может помочь определить объявления функций, которые могли быть пропущены или предупреждать вас, если параметры определения функции не соответствуют значениям в типе роли функции.