Управление объектами

В этом разделе рассматривается правильное использование типов объектов API платформы фильтрации Windows (МПП).

Сеансы

API МПП ориентирован на сеансы, и большинство вызовов функций выполняются в контексте сеанса. Новый сеанс клиента создается путем вызова FwpmEngineOpen0. Сеанс завершается, когда клиент вызывает FwpmEngineClose0 или завершается клиентский процесс. При уничтожении сеанса (намеренно или в результате запуска RPC) базовая подсистема фильтрации (BFE) сначала прерывает любую существующую транзакцию.

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

Transactions

API МПП является транзакционным, и большинство вызовов функций выполняются в контексте транзакции. Вызывающие могут использовать FwpmTransactionBegin0, FwpmTransactionCommit0 и FwpmTransactionAbort0 для явного управления транзакциями. Однако если вызов функции выполняется вне явной транзакции, он будет выполняться в неявной транзакции. Если транзакция выполняется, то при завершении сеанса она автоматически прерывается. Неявные транзакции никогда не прерываются принудительно.

Транзакции доступны только для чтения или чтения и записи и обеспечивают строгую семантику ATOMIC Consistent Isolated Durable (ACID).

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

Если операция завершается сбоем во время транзакции, это не влияет на общее состояние транзакции. Например, предположим, что клиент начинает транзакцию и успешно вызывает FwpmFilterAdd0 три раза, прежде чем четвертый вызов завершится ошибкой. Теперь у клиента есть возможность:

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

При запуске транзакции BFE будет ожидать истечения срока действия txnWaitTimeoutInMSec сеанса, чтобы получить блокировку. Если блокировка не получена в течение этого времени, получение блокировки (и вызов FwpmTransactionBegin0 ) завершится ошибкой. Это не позволяет клиентам на неопределенный срок не отвечать на запросы. Если клиент не указал время ожидания блокировки, по умолчанию используется значение 15 секунд.

Каждая транзакция также имеет время ожидания блокировки. Это максимальное время, в течение которого она может владеть блокировкой. Если владелец не освобождает блокировку в течение этого времени, транзакция принудительно прерывается, что приводит к освобождению блокировки. Время ожидания блокировки не настраивается. Он бесконечен для вызывающих объектов в режиме ядра и один час для вызывающих элементов пользовательского режима. Если транзакция принудительно прервана, следующий вызов, выполненный в этой транзакции, завершится сбоем с FWP_E_TXN_ABORTED.

Время существования объекта

Объекты могут иметь одно из четырех возможных значений времени существования:

  • Динамический — объект является динамическим, только если он добавляется с помощью динамического дескриптора сеанса. Динамические объекты живут до тех пор, пока они не будут удалены или сеанс владения не завершится.
  • Статические — объекты являются статическими по умолчанию. Статические объекты живут до их удаления, остановки BFE или завершения работы системы.
  • Постоянные — постоянные объекты создаются путем передачи соответствующего флага FWPM_*_FLAG_PERSISTENT функции Fwpm*Add0 . Постоянные объекты живут до удаления.
  • Встроенные — встроенные объекты предопределяются BFE и не могут быть добавлены или удалены. Они живут вечно.

Фильтры в уровнях режима ядра можно пометить как фильтры во время загрузки, передав соответствующий флаг в FwpmFilterAdd0. Фильтры времени загрузки добавляются в систему при запуске драйвера TCP/IP и удаляются после завершения инициализации BFE. Постоянные объекты добавляются при запуске BFE.

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

Связи объектов

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

Объект нельзя удалить, пока не будут удалены все объекты, ссылающиеся на него.

Идентификаторы LUID и GUID

Все объекты API ПППП пользовательского режима (FWPM) идентифицируются с помощью глобально уникального идентификатора (GUID) и ссылаются на другие объекты по идентификаторам GUID. Идентификатор GUID должен быть уникальным только в пределах типа объекта. Например, фильтр и контекст поставщика могут иметь один и тот же ИДЕНТИФИКАТОР GUID, но два фильтра — нет. При добавлении нового объекта вызывающие объекты могут назначить идентификатор GUID объекта или оставить его инициализированным с нуля и разрешить BFE назначить GUID.

Все объекты API ВПП в режиме ядра (FWPS) идентифицируются с помощью локально уникального идентификатора (LUID) и ссылаются на другие объекты по их LUID. Переход с GUID на LUID позволяет МПП экономить нестраничный пул и оптимизировать обработку во время выполнения. Ширина LUID зависит от типа объекта и варьируется от UINT16 до UINT64. LuIDвсегда назначается BFE.