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


Рекомендации по переносу устаревших драйверов фильтров

Разработчикам рекомендуется переносить устаревшие драйверы фильтров в модель диспетчера фильтров, чтобы получить лучшую функциональность для драйверов фильтров и повысить надежность системы. Опытные разработчики могут относительно легко перенести устаревший драйвер фильтра в драйвер минифильтра. Разработчики драйверов фильтрации в Корпорации Майкрософт рекомендуют следующий подход:

  • Начните с набора тестов надежной регрессии, чтобы проверить поведение между устаревшим драйвером фильтра и перенесенным драйвером минифильтра.

  • Создайте оболочку драйвера минифильтра и систематически перемещайте функциональные возможности из устаревшего драйвера фильтра в драйвер минифильтра. Например, можно получить вложение, а затем портировать одну операцию за раз, проверяя после каждой операции.

  • Измените последний обмен данными в режиме пользователя и ядра, чтобы использовать существующие средства для тестирования драйвера минифильтра.

  • Скомпилируйте с помощью PREfast и выполните тестирование с параметром проверки ввода-вывода filter verifier (Фильтр проверки ввода-вывода) в включенном средства проверки драйверов.

В процессе переноса следует просмотреть весь устаревший код драйвера фильтра, чтобы воспользоваться всеми преимуществами диспетчера фильтров. В частности, учитывайте следующее:

  • Операции ввода-вывода на основе IRP и быстрые операции ввода-вывода могут выполняться через одну и ту же операцию, когда это необходимо, что помогает сократить дублирование кода.

  • При регистрации для операций драйвер мини-фильтра может явно игнорировать все операции ввода-вывода подкачки и кэшированные операции ввода-вывода, что избавляет от необходимости в коде проверка этих операций.

  • Уведомления экземпляра значительно упрощают логику подключения и отсоединения.

  • Регистрируйтесь только для операций, которые должен обрабатывать драйвер минифильтра; вы можете игнорировать все остальное.

  • Воспользуйтесь преимуществами поддержки контекста и управления именами диспетчера фильтров.

  • Воспользуйтесь поддержкой диспетчера фильтров для выдачи не рекурсивных операций ввода-вывода.

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

  • Не забудьте освободить ссылки по завершении с именем или контекстом.

  • Порты завершения в пользовательском режиме добавляют мощный метод для создания очередей. Вероятно, потребуется только одно подключение к одному именованный порт.

В следующей таблице перечислены распространенные операции в устаревшем драйвере фильтра и их сопоставление с моделью диспетчера фильтров.

Устаревшая модель драйвера фильтра Модель диспетчера фильтров

Сквозная операция без процедуры завершения

Если драйвер мини-фильтра никогда не работает для этого типа операций ввода-вывода, не регистрируйте подпрограмму обратного вызова перед операцией или после операции для этой операции.

В противном случае верните FLT_PREOP_SUCCESS_NO_CALLBACK из подпрограммы обратного вызова перед операцией, зарегистрированной для этой операции.

См . раздел Возврат FLT_PREOP_SUCCESS_NO_CALLBACK.

Сквозная операция с подпрограммой завершения

Возврат FLT_PREOP_SUCCESS_WITH_CALLBACK из процедуры обратного вызова перед операции.

См . раздел Возврат FLT_PREOP_SUCCESS_WITH_CALLBACK.

Операция pend в подпрограмме обратного вызова перед операцией

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

Поставить работу в рабочий поток, вызвав подпрограммы поддержки, такие как FltAllocateDeferredIoWorkItem и FltQueueDeferredIoWorkItem.

Возврат FLT_PREOP_PENDING из процедуры обратного вызова перед операции.

Когда вы будете готовы вернуть операцию ввода-вывода в диспетчер фильтров, вызовите FltCompletePendedPreOperation.

См. раздел Ожидание операции ввода-вывода в процедуре обратного вызова перед операцией.

Операция pend в подпрограмме обратного вызова после операции

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

Поставить работу в рабочий поток, вызвав подпрограммы поддержки, такие как FltAllocateGenericWorkItem и FltQueueGenericWorkItem.

Возврат FLT_POSTOP_MORE_PROCESSING_REQUIRED из процедуры обратного вызова после операции.

Когда все будет готово к возврату операции ввода-вывода в диспетчер фильтров, вызовите Метод FltCompletePendedPostOperation.

См. раздел Ожидание операции ввода-вывода в процедуре обратного вызова после операции.

Синхронизация операции

Возврат FLT_PREOP_SYNCHRONIZE из процедуры обратного вызова перед операции.

См . раздел Возврат FLT_PREOP_SYNCHRONIZE.

Завершение операции в процедуре обратного вызова перед операцией

Задайте состояние конечной операции и сведения в элементе IoStatusструктуры FLT_CALLBACK_DATA для операции.

Возврат FLT_PREOP_COMPLETE из процедуры обратного вызова перед операции.

См. раздел Завершение операции ввода-вывода в процедуре обратного вызова перед операцией.

Завершение операции после ее выполнения в процедуре обратного вызова перед операцией

Задайте состояние конечной операции и сведения в элементе IoStatusструктуры FLT_CALLBACK_DATA для операции.

Вызовите FltCompletePendedPreOperation из рабочего потока, обрабатывая операцию ввода-вывода, передав FLT_PREOP_COMPLETE в качестве параметра CallbackStatus .

См. раздел Завершение операции ввода-вывода в процедуре обратного вызова перед операцией.

Выполнение всех работ по завершению в подпрограмме завершения

Возвращает FLT_POSTOP_FINISHED_PROCESSING из процедуры обратного вызова после операции.

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

Выполнение работы по завершению в безопасном IRQL

Вызовите Метод FltDoCompletionProcessingWhenSafe из подпрограммы обратного вызова после операции.

См . раздел Обеспечение выполнения обработки завершения в безопасном IRQL.

Сигнал события из подпрограммы завершения

Возвращает FLT_PREOP_SYNCHRONIZE из процедуры обратного вызова перед операцией для этой операции.

Диспетчер фильтров вызывает подпрограмму обратного вызова после операции в том же контексте потока, что и подпрограмма обратного вызова перед операции, в irQL <= APC_LEVEL.

См . раздел Возврат FLT_PREOP_SYNCHRONIZE.

Сбой успешной операции создания

Вызовите Метод FltCancelFileOpen из подпрограммы обратного вызова после операции для операции создания.

Задайте соответствующее значение NTSTATUS ошибки в элементе IoStatusструктуры FLT_CALLBACK_DATA для операции.

Возврат FLT_POSTOP_FINISHED_PROCESSING.

См. раздел Сбой операции ввода-вывода в процедуре обратного вызова после операции.

Запретить ввод-вывод через быстрый путь ввода-вывода для операции ввода-вывода

Возвращает FLT_STATUS_DISALLOW_FAST_IO из процедуры обратного вызова перед операцией.

См. раздел Запрет быстрой операции ввода-вывода в процедуре обратного вызова перед операцией.

Изменение параметров операции ввода-вывода

Задайте измененные значения параметров в элементе Iopbструктуры FLT_CALLBACK_DATA для операции.

Пометьте структуру FLT_CALLBACK_DATA как грязное, вызвав FltSetCallbackDataDirty, за исключением случаев, когда вы изменили содержимое элемента IoStatus структуры FLT_CALLBACK_DATA.

См. раздел Изменение параметров для операции ввода-вывода.

Блокировка буфера пользователя для операции

Используйте методы и рекомендации, описанные в статье Доступ к пользовательским буферам для операций ввода-вывода.