Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Разработчикам рекомендуется переносить устаревшие драйверы фильтров в модель диспетчера фильтров, чтобы получить лучшие функциональные возможности для драйверов фильтров и повысить надежность системы. Опытным разработчикам должно быть относительно легко переписать устаревший драйвер фильтра в минифильтр-драйвер. Разработчики драйверов фильтрации в Корпорации Майкрософт рекомендуют следующий подход:
Начните с надежного набора тестов регрессии, чтобы проверить поведение между устаревшим драйвером фильтра и перенесенным драйвером минифильтра.
Создайте оболочку драйвера минифильтра и систематически перемещайте функциональные возможности из устаревшего драйвера фильтра в драйвер минифильтра. Например, настройте работу вложений, а затем перенесите одну операцию за раз, проверяя после каждой операции.
Измените взаимодействие между пользовательским и ядровым режимами в последнюю очередь, чтобы можно было использовать существующие средства для тестирования драйвера мини-фильтра.
Скомпилируйте с помощью PREfast и проверьте параметр проверки ввода-вывода средства проверки фильтра в включенном средство проверки драйверов.
Во время переноса необходимо просмотреть весь код драйвера устаревших фильтров, чтобы воспользоваться всеми преимуществами возможностей диспетчера фильтров. В частности, помните следующее:
Операции ввода-вывода на основе IRP и быстрых операций ввода-вывода могут выполняться через ту же операцию, когда это необходимо, что помогает сократить дублирование кода.
При регистрации для операций драйвер минифильтра может явно игнорировать все операции ввода-вывода на разбиение по страницам и кэшированные операции ввода-вывода, что устраняет необходимость проверки кода.
Экземплярные уведомления значительно упрощают логику присоединения и отсоединения.
Зарегистрируйтесь только для операций, которые должен обрабатывать драйвер минифильтра; вы можете игнорировать все остальное.
Используйте возможности поддержки контекста менеджера фильтров и системы управления именами.
Воспользуйтесь поддержкой диспетчера фильтров для выполнения не-рекурсивных операций ввода-вывода.
В отличие от устаревших драйверов фильтров, драйверы минифильтра не могут полагаться на локальные переменные для поддержания контекста от обработки перед выполнением до обработки после операции. Рассмотрите возможность выделения списка lookaside (буферного списка) для хранения состояния операции.
Не забудьте освободить ссылки, когда закончите использовать имя или контекст.
Порты завершения в режиме пользователя предоставляют мощный инструмент для создания очередей. Возможно, вам потребуется только одно соединение с одним именованным портом.
В следующей таблице перечислены распространенные операции в устаревшем драйвере фильтра и их сопоставление с моделью диспетчера фильтров.
| Устаревшая модель драйвера фильтра | Модель диспетчера фильтров |
|---|---|
Сквозная операция без процедуры завершения |
Если ваш драйвер мини-фильтра никогда не работает с этой операцией ввода-вывода, не регистрируйте подпрограмму обратного вызова предоперационную или постоперационную для этой операции. В противном случае верните FLT_PREOP_SUCCESS_NO_CALLBACK из предоперационного обратного вызова, зарегистрированного для этой операции. |
Транзитная операция с подпрограммой завершения |
Возвращает FLT_PREOP_SUCCESS_WITH_CALLBACK из подпрограммы обратного вызова предварительной операции. |
Операция пера в подпрограмме обратного вызова перед выполнением |
Вызовите FltLockUserBuffer по мере необходимости, чтобы гарантировать, что пользовательские буферы правильно заблокированы для доступа из рабочего потока. Добавьте задачу в рабочий поток с помощью вызова вспомогательных процедур, таких как FltAllocateDeferredIoWorkItem и FltQueueDeferredIoWorkItem. Верните FLT_PREOP_PENDING из подпрограммы обратного вызова предварительной операции. Когда вы готовы вернуть операцию ввода-вывода в диспетчер фильтров, вызовите FltCompletePendedPreOperation. См. ожидание операции ввода-вывода в подпрограмме обратного вызова до выполнения. |
Операция пера в подпрограмме обратного вызова после операции |
В подпрограмме обратного вызова до выполнения операции вызовите FltLockUserBuffer, чтобы обеспечить правильную блокировку пользовательских буферов, чтобы их можно было использовать в рабочем потоке. Поместите работу в рабочий поток, вызвав подпрограммы поддержки, такие как FltAllocateGenericWorkItem и FltQueueGenericWorkItem. Возвращайте FLT_POSTOP_MORE_PROCESSING_REQUIRED из подпрограммы обратного вызова послеоперационной обработки. Когда вы готовы вернуть операцию ввода-вывода в диспетчер фильтров, вызовите FltCompletePendedPostOperation. См. ожидание операции ввода-вывода в подпрограмме обратного вызова после операции. |
Синхронизация операции |
Возвращает 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. |
Провал в успешно выполненной операции создания |
Вызовите 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. |
Заблокируйте буфер пользователя для операции. |
Используйте методы и рекомендации, описанные в разделе «Доступ к пользовательским буферам для операции ввода-вывода». |