フレームワーク オブジェクトのコンテキスト領域
オブジェクトコンテキスト領域 は、ドライバーがオブジェクトに割り当て可能な、ページ不可能な余分なメモリ領域です。 各フレームワークベースのドライバーは、ドライバーが受信したり作成したりしたすべてのフレームワークオブジェクトに対して 1 つ以上のオブジェクト固有のコンテキスト領域を作成できます。
フレームワークベースのドライバーは、値またはポインターによって、すべてのオブジェクト固有データをそのデータが属するオブジェクトのコンテキスト領域内に格納する必要があります。
たとえば、USB デバイス用のドライバーは、そのフレームワークデバイスオブジェクトのコンテキスト領域を作成する場合があります。 コンテキスト領域では、ドライバーは、デバイスのUSB_DEVICE_DESCRIPTORやUSB_CONFIGURATION_DESCRIPTOR構造などのデバイス固有の情報に加えて、デバイスインターフェイスのパイプを表すコレクション オブジェクトへのハンドルを格納する場合があります。
フレームワークは、あるドライバーから別のドライバーにフレームワークオブジェクトを渡さないため、オブジェクトのコンテキスト領域を使用して2 つのドライバー間でデータを渡すことはできません。
オブジェクトのコンテキスト領域を定義するには、1 つ以上の構造を作成する必要があります。 各構造は、個別のコンテキスト領域を表します。 ドライバーは、各構造メンバーを使用して、オブジェクト固有の情報の一部を格納します。 さらに、ドライバーは、構造に対してアクセサーメソッドを生成するようにフレームワークに要求する必要があります。 このアクセサーメソッドは、オブジェクトハンドルを入力として受け取り、オブジェクトのコンテキスト領域のアドレスを返します。
ドライバーが WdfDeviceCreateのようなオブジェクト作成メソッドを呼び出すたびに、このメソッドは必要に応じてコンテキスト領域を割り当てます。 すべてのオブジェクト作成メソッドは、オプションのWDF_OBJECT_ATTRIBUTES構造を入力として受け入れます。 この構造は、フレームワークがオブジェクトに割り当てるコンテキスト領域を表します。
ドライバーがオブジェクトの作成メソッドを呼び出した後にオブジェクトにコンテキスト領域を追加するには、ドライバーは WdfObjectAllocateContext メソッドを呼び出すことができる。このメソッドは、オブジェクト作成メソッドと同様に、WDF_OBJECT_ATTRIBUTES構造を入力として受け入れます。
フレームワークがオブジェクトにコンテキスト領域を割り当てるときに、コンテキスト領域もゼロ初期化します。
フレームワークまたはドライバーがフレームワークオブジェクトを削除すると、フレームワークはオブジェクトのすべてのコンテキスト領域を削除します。
ドライバーがオブジェクトの作成時に、ドライバーが割り当てたバッファへのポインターを格納するためにコンテキスト領域を使用する場合、ドライバーは、オブジェクトの削除時にバッファーの割り当てを解除するEvtCleanupCallback関数を提供する必要があります。
ドライバーが作成するオブジェクトのオブジェクトのコンテキスト領域構造とアクセサーメソッドを定義するには、ドライバーは次のステップを使用する必要があります。
格納したいデータを記述する構造を定義します。 たとえば、ドライバーのデバイスオブジェクトのコンテキストデータを作成する場合、ドライバーは、MY_DEVICE_CONTEXTという構造を定義する可能性があります。
WDF_DECLARE_CONTEXT_TYPE マクロまたは WDF_DECLARE_CONTEXT_TYPE_WITH_NAMEマクロを使用します。 これらのマクロはどちらも次の操作を行います。
- WDF_OBJECT_CONTEXT_TYPE_INFO構造を作成して初期化します。
- ドライバーが後でオブジェクトのコンテキスト領域にアクセスするために使用するアクセサーメソッドを定義します。 アクセサーメソッドの戻り値は、オブジェクトのコンテキスト領域へのポインターです。
WDF_DECLARE_CONTEXT_TYPEマクロは、構造の名前からアクセサーメソッドの名前を作成します。 たとえば、コンテキスト構造の名前がMY_DEVICE_CONTEXTである場合、マクロはWdfObjectGet_MY_DEVICE_CONTEXTというアクセサーメソッドを作成します。
WDF_DECLARE_CONTEXT_TYPE_WITH_NAMEマクロを使用することで、アクセサーメソッドの名前を指定できます。 たとえば、デバイスオブジェクト用のコンテキストアクセサーメソッドの名前として GetMyDeviceContextを指定する可能性があります。
WDF_OBJECT_ATTRIBUTES_INITを呼び出して、オブジェクトのWDF_OBJECT_ATTRIBUTES構造を初期化します。
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPEマクロを使用して、WDF_OBJECT_ATTRIBUTES構造のContextTypeInfoメンバーをWDF_OBJECT_CONTEXT_TYPE_INFO構造のアドレスに設定します。
WdfDeviceCreateなどのオブジェクト作成メソッドを呼び出します。
ドライバーがオブジェクトを作成した後、ドライバーはいつでもWdfObjectAllocateContextを呼び出して、オブジェクトに追加のコンテキスト領域を追加できます。
ステップ 1 と 2 ではグローバルデータ構造を定義し、ドライバーが呼び出し可能なルーチンを作成するため、ドライバーは、グローバルデータを宣言するドライバーのエリア(通常はヘッダーファイル) でこれらのステップを完了する必要があります。 これらのステップは、ドライバーのルーチン内から完了してはなりません。
ドライバーは、WdfDeviceCreateを呼び出すEvtDriverDeviceAddコールバック関数など、オブジェクトを作成するドライバールーチン内からステップ 3、4、5 を完了する必要があります。
フレームワークは、ドライバーの代わりに、フレームワークリクエストオブジェクトとフレームワークファイル オブジェクトという 2 種類のオブジェクトを作成できます。 ドライバーは、WdfDeviceInitSetRequestAttributes と WdfDeviceInitSetFileObjectConfigをそれぞれ呼び出すことによって、これらのオブジェクトのコンテキスト領域を登録できます。 ドライバーは、WdfObjectAllocateContextを呼び出すことによって、これらのオブジェクトのコンテキスト領域を割り当てることもできます。
オブジェクトが作成された後、ドライバーは、以下のいずれかの方法でオブジェクトのコンテキスト領域へのポインターを取得できます:
WDF_DECLARE_CONTEXT_TYPE や WDF_DECLARE_CONTEXT_TYPE_WITH_NAME マクロを使用して、前のステップ 2 で作成したコンテキストアクセサーメソッドを呼び出します。
WdfObjectGetTypedContextを呼び出して、ドライバー定義のコンテキスト構造の名前を指定します。
ドライバーにコンテキスト領域ポインターがある場合は、WdfObjectContextGetObjectを呼び出すことによって、そのコンテキスト領域が属するオブジェクトを見つけることができます。