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

Примечание

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

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

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

DRIVER_UNLOAD CsampUnload;

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

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

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

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

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

DRIVER_UNLOAD

Выгрузить

DRIVER_ADD_DEVICE

AddDevice

DRIVER_DISPATCH Dispatch_type(type)

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

IO_COMPLETION_ROUTINE

IoCompletion

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

DRIVER_CANCEL

Отменить

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

IO_DPC_ROUTINE

DpcForIsr

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

KDEFERRED_ROUTINE

CustomDpc

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

KSERVICE_ROUTINE

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

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

REQUEST_POWER_COMPLETE

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

WORKER_THREAD_ROUTINE

Обычной

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

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

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

Начиная с Windows 10 версии 2004, объявления типов ролей функции для подпрограмм диспетчеризации автоматически уточняются с их категорией IRP на основе инициализации таблицы DriverObject-MajorFunction> в подпрограмме 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, драйвер должен использовать только базовый или расширенный стиль, показанный выше. Verficiation SDV в драйвере не будет работать должным образом , если один из этих двух методов не используется.

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

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

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

IO_COMPLETION_ROUTINE myCompletionRoutine;

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

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

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

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