フレームワーク オブジェクトのコレクション

ドライバーは、フレームワークコレクション オブジェクトによって表されるコレクションにフレームワークオブジェクトをグループ化できます。

たとえば、ドライバーが大きな I/O リクエストを表すフレームワークリクエストオブジェクトを受信した場合、ドライバーは、大きなリクエストを、I/O ターゲットに送信できる小さなリクエストに分割する必要があります。 大きなリクエストをより小さなリクエストに分割するには、ドライバーは、小さなリクエストを表すリクエストオブジェクトのセットを作成する必要があります。 これらのドライバーによって作成されたリクエストオブジェクトを追跡するために、ドライバーはコレクション オブジェクトを作成し、コレクションに追加する場合があります。

通常、オブジェクト コレクション内のオブジェクトは 1 種類のフレームワーク オブジェクトで構成されますが、ドライバーはさまざまな種類のオブジェクトで構成されるコレクションを作成できます。

ドライバーはコレクションのコレクションを作成することもできます。 つまり、コレクションはコレクション オブジェクトのセットで構成できます。

フレームワークベースのドライバーは、オブジェクトコレクションに対して次の操作を実行できます。

  • コレクションオブジェクトを作成します。

    新しいコレクションを作成するために、ドライバーはWdfCollectionCreateを呼び出すことができます。

  • コレクションにオブジェクトを追加します。

    コレクションにオブジェクトを追加するために、ドライバーはWdfCollectionAddを 1 回以上呼び出すことができます。 WdfCollectionAdd呼び出すたびに、コレクションの末尾にオブジェクトが追加され、追加されたオブジェクトの参照カウントが増加します。

  • コレクションのオブジェクトの削除

    コレクションからオブジェクトを削除し、その参照カウントをデクリメントために、ドライバーはWdfCollectionRemoveまたはWdfCollectionRemoveItemを呼び出すことができます。 オブジェクトが削除されると、削除されたオブジェクト以降のすべてのオブジェクトのインデックスが自動的にデクリメントされます。

  • コレクション内のオブジェクトの数を取得します。

    コレクションに含まれるオブジェクトの数を確認するために、ドライバーは WdfCollectionGetCountを呼び出すことができます。

  • コレクション内のオブジェクトへのハンドルを取得します。

    ドライバーがWdfCollectionGetItemを呼び出し、入力引数としてインデックス値を指定する場合、ドライバーは、このインデックス値に関連付けられたオブジェクトへのハンドルを受信します。 (インデックス値0 はコレクション内の最初のオブジェクトを表し、インデックス値1 は2番目のオブジェクトを表し、以下同様--リンクリストのようになります。ドライバーがコレクションから項目i を削除すると、項目i+1 が項目iになります。)

    ドライバーは、WdfCollectionGetFirstItemまたは WdfCollectionGetLastItemを呼び出して、コレクションに追加された最初または最後の項目へのハンドルを取得することもできます。

  • コレクションをロックします。

    ドライバーは、WdfWaitLockAcquireを呼び出してIRQL = PASSIVE_LEVEL のコレクションへのアクセスを同期するか、WdfSpinLockAcquireを呼び出してIRQL = DISPATCH_LEVELのコレクションへのアクセスを同期することができます。 ドライバーがロックを取得した後は、WdfWaitLockAcquireまたはWdfSpinLockAcquireを呼び出すドライバー内の他のコードによってコレクションにアクセスできなくなります。 コレクションに対する操作を完了した後、ドライバーは WdfWaitLockReleaseを呼び出す必要があります。

    WdfWaitLockAcquireorWdfSpinLockAcquireを呼び出しても、他のコードもWdfWaitLockAcquireまたはWdfSpinLockAcquireを呼び出さない限り、ドライバー内の他のコードが同時にコレクションにアクセスすることは妨げられません。

  • コレクションを削除します。

    コレクション オブジェクトを削除するために、ドライバーは WdfObjectDeleteを呼び出すことができます。 ただし、通常、ドライバーはコレクションを作成するときに親オブジェクトを指定し、フレームワークは親オブジェクトを削除するときにコレクション オブジェクトを削除します。

    たとえば、ドライバーは、大きな I/O リクエストをより小さなリクエストに分割できるようにリクエストオブジェクトのセットを作成する場合、大きな I/O リクエストのリクエストオブジェクトをコレクション オブジェクトの親オブジェクトにすることができます。 最終的に、ドライバーの I/O ターゲットは WdfRequestCompleteを呼び出して、より小さなリクエストを完了します。 その時点で、ドライバーは大きな I/O リクエストに対してWdfRequestCompleteを呼び出すことができるため、フレームワークはリクエストオブジェクトとその子オブジェクトであるコレクションオブジェクトを削除します。

    フレームワークが、削除されていないオブジェクトを含むコレクションオブジェクトを削除すると、フレームワークはコレクションからオブジェクトを削除し、その参照カウントをデクリメントしますが、コレクション オブジェクトだけを削除します。

場合によっては、ドライバーは、コレクション内のすべてのオブジェクトを検査する必要があります。 次のコード例は、この状況を示しています。

WdfWaitLockAcquire(CollectionLockHandle, NULL);
ItemCount = WdfCollectionGetCount(CollectionHandle);
for (i=0; i<ItemCount; i++) {
    ObjectHandle = WdfCollectionGetItem(CollectionHandle, i);
    // 1. Call object-specific methods to obtain object properties.
    // 2. Perform object-specific operations.
    }
WdfWaitLockRelease(CollectionLockHandle);