オブジェクト管理
このセクションでは、Windows フィルタリング プラットフォーム (WFP) API オブジェクトの種類の正しい使用方法について説明します。
セッション
WFP API はセッション指向であり、ほとんどの関数呼び出しはセッションのコンテキスト内で行われます。 FwpmEngineOpen0呼び出すことによって、新しいクライアント セッションが作成されます。 セッションは、クライアントが FwpmEngineClose0呼び出すか、クライアント プロセスが終了したときに終了します。 セッションが意図的に、または RPC ランダウンによって破棄されると、基本フィルター エンジン (BFE) は最初に既存のトランザクションを中止します。
新しいセッションを作成するときに、呼び出し元は FwpmEngineOpen0に FWPM_SESSION_FLAG_DYNAMIC フラグを渡して動的セッションを作成できます。 動的セッション中に追加されたオブジェクトは、セッションの終了時に自動的に削除されます。
トランザクション
WFP API はトランザクションであり、ほとんどの関数呼び出しはトランザクションのコンテキスト内で行われます。 呼び出し元は、FwpmTransactionBegin0、FwpmTransactionCommit0、および FwpmTransactionAbort0 を使用して、トランザクションを明示的に制御できます。 ただし、関数呼び出しが明示的なトランザクションの外部で行われた場合、暗黙的なトランザクション内で実行されます。 トランザクションが進行中の場合、セッションが終了すると、自動的に中止されます。 暗黙的なトランザクションは強制的に中止されることはありません。
トランザクションは読み取り専用または読み取り/書き込みのいずれかであり、厳密なアトミック整合性分離 Durable (ACID) セマンティクスを適用します。
各クライアント セッションでは、進行中のトランザクションを一度に 1 つだけ持つことができます。 呼び出し元が最初のトランザクションをコミットまたは中止する前に 2 番目のトランザクションを開始しようとすると、BFE はエラーを返します。
トランザクションの実行中に操作が失敗した場合、トランザクションの全体的な状態には影響しません。 たとえば、クライアントがトランザクションを開始し、4 回目の呼び出しが失敗 前に FwpmFilterAdd0 を 3 回正常に呼び出すとします。 これで、クライアントには次のオプションがあります。
- トランザクションを中止すると、どのフィルターも追加されません。
- トランザクションをコミットすると、最初の 3 つのフィルターが追加されます。
- 失敗した FwpmFilterAdd0を再試行するなど、さらに多くの操作を続行します。
トランザクションを開始すると、BFE はセッションの txnWaitTimeoutInMSec が期限切れになるまで待機してロックを取得します。 この時間内にロックが取得されない場合、ロックの取得 (および FwpmTransactionBegin0 呼び出し) は失敗します。 これにより、クライアントが無期限に応答に失敗するのを防ぐことができます。 クライアントがロック タイムアウトを指定しなかった場合、既定値は 15 秒です。
各トランザクションにもロック タイムアウトがあります。 これは、ロックを所有できる最大時間です。 所有者がこの時間内にロックを解放しない場合、トランザクションは強制的に中止され、ロックが解放されます。 ロック タイムアウトは構成できません。 カーネル モードの呼び出し元では無限で、ユーザー モードの呼び出し元の場合は 1 時間です。 トランザクションが強制的に中止された場合、そのトランザクション内で行われる次の呼び出しは、FWP_E_TXN_ABORTEDで失敗します。
オブジェクトの有効期間
オブジェクトには、次の 4 つの有効期間のいずれかを指定できます。
- 動的 — 動的セッション ハンドルを使用してオブジェクトが追加された場合にのみ動的です。 動的オブジェクトは、削除されるか、所有セッションが終了するまでライブ状態になります。
- Static — オブジェクトは既定で静的です。 静的オブジェクトは、削除されるか、BFE が停止するか、システムがシャットダウンされるまで存続します。
- 永続的 — 永続的オブジェクトは、適切な FWPM_*_FLAG_PERSISTENT フラグを Fwpm*Add0 関数に渡すことによって作成されます。 永続オブジェクトは、削除されるまで存続します。
- 組み込み — 組み込みオブジェクトは BFE によって定義済みであり、追加または削除することはできません。 彼らは永遠に生きています。
カーネル モード レイヤーのフィルターは、FwpmFilterAdd0 に適切なフラグを渡すことで、ブート時フィルターとしてマークできます。 ブート時フィルターは、TCP/IP ドライバーの起動時にシステムに追加され、BFE の初期化が完了すると削除されます。 永続オブジェクトは、BFE の開始時に追加されます。
多くの場合、プロバイダーが無効になっている場合、ポリシー プロバイダーは永続的なポリシーを適用したくない場合があります。 プロバイダーを追加するときに、呼び出し元はオプションの Windows サービス名を指定できます。 永続オブジェクトを追加する場合、呼び出し元は必要に応じて、そのオブジェクトを "所有" するプロバイダーを指定できます。 サービスの開始時に、BFE は、永続的なオブジェクトがプロバイダーに関連付けられていない場合、または関連付けられているプロバイダーに Windows サービス名がない場合、または関連付けられている Windows サービスが自動開始に設定されている場合にのみ、システムに追加します。
オブジェクトの関連付け
一部のオブジェクトには、他のオブジェクトへの参照があります。 たとえば、フィルターは常にレイヤーを参照し、吹き出しとプロバイダー コンテキストを参照できます。 オブジェクトは、有効期間が短い可能性があるオブジェクトを参照できません。 したがって、動的オブジェクトは、別のセッションから動的オブジェクトを参照することはできません。 静的オブジェクトは動的オブジェクトを参照できません。 永続オブジェクトは、動的オブジェクト、静的オブジェクト、または別のプロバイダーが所有する永続オブジェクトを参照できません。
オブジェクトを参照するすべてのオブジェクトが最初に削除されるまで、オブジェクトを削除することはできません。
LUID と GUID
すべてのユーザー モード WFP API オブジェクト (FWPM) は、グローバル一意識別子 (GUID) で識別され、GUIDで他のオブジェクトを参照します。 GUID は、オブジェクト型内でのみ一意である必要があります。 たとえば、フィルターとプロバイダー コンテキストは、同じ GUIDを持つことができますが、2 つのフィルターを使用することはできません。 新しいオブジェクトを追加するときに、呼び出し元は、オブジェクトの GUID を割り当てたり、ゼロ初期化のままにして、BFE に GUID割り当てさせることができます。
すべてのカーネル モード WFP API オブジェクト (FWPS) は、ローカル一意識別子 (LUID) によって識別され、その LUID によって他のオブジェクトを参照します。 GUID から LUID に切り替えると、WFP でページ以外のプールを節約し、実行時の処理を最適化できます。 LUID の幅は、UINT16 から UINT64までのオブジェクトの種類と範囲によって異なります。 LUIDは常に BFE によって割り当てられます。