UMDF 1 から UMDF 2 へのドライバーの移植
このトピックでは、ユーザー モード ドライバー フレームワーク (UMDF) 1 ドライバーを UMDF 2 に移植する方法について説明します。 (Visual Studio プロジェクトではなく) ソース/ディレクトリ ファイルを使用する UMDF 1 ドライバーから開始するか、Visual Studio プロジェクトに含まれる UMDF 1 ドライバーを変換できます。 結果は、Visual Studio の UMDF 2 ドライバー プロジェクトになります。 UMDF 2 ドライバーは、デスクトップ エディション (Home、Pro、Enterprise、Education) 用の Windows 10 と Windows 10 Mobile の両方で実行されます。
Echo ドライバーサンプルは、UMDF 1 から UMDF 2 に移植されたドライバーの例です。
はじめに
開始するには、Visual Studio で新しいドライバー プロジェクトを開きます。 Visual C++->Windows Driver->WDF->User Mode Driver (UMDF 2) テンプレートを選択します。 Visual Studio は、ドライバーが実装する必要があるコールバック関数のスタブを含む、部分的に設定されたテンプレートを開きます。 この新しいドライバー プロジェクトは、UMDF 2 ドライバーの基盤になります。 導入する必要があるコードの種類のガイドとして、UMDF 2 Echo サンプルを使用します。
次に、既存の UMDF 1 ドライバー コードを確認し、オブジェクト マッピングを決定します。 UMDF 1 の各 COM オブジェクトには、UMDF 2 の対応する WDF オブジェクトがあります。 たとえば、IWDFDevice インターフェイスは、WDFDEVICE ハンドルによって表される WDF デバイス オブジェクトにマップされます。 UMDF 1 のフレームワークによって提供されるほぼすべてのインターフェイス メソッドには、UMDF 2 に対応するメソッドがあります。 たとえば、IWDFDevice::GetDefaultIoQueue は WdfDeviceGetDefaultQueue にマップされます。
同様に、ドライバーが提供するコールバック関数には、2 つのバージョンに相当するものがあります。 UMDF 1 では、ドライバーが提供するインターフェイス (IDriverEntry を除く) の名前付け規則は IObjectCallbackXxx ですが、UMDF 2 ではドライバーが提供するルーチンの名前付け規則は EvtObjectXxxです。 たとえば、IDriverEntry::OnDeviceAdd コールバック メソッドは EvtDriverDeviceAdd にマップされます。
ドライバーは UMDF 1 と 2 の両方でコールバック関数を実装しますが、ドライバーがコールバックへポインターを提供する方法は異なります。 UMDF 1 では、ドライバーは、ドライバーが提供するインターフェイスのメンバーとしてコールバック メソッドを実装します。 ドライバーは、フレームワーク オブジェクトを作成するときに、たとえば IWDFDriver::CreateDevice を呼び出すことによって、フレームワークにこれらのインターフェイスを登録します。
UMDF 2 では、ドライバーは、WDF_DRIVER_CONFIG や WDF_IO_QUEUE_CONFIG などの構成構造でドライバーによって提供されるコールバック関数へのポインターを提供します。
オブジェクトの有効期間の管理
UMDF 1 を使用するドライバーは、オブジェクトを削除しても安全な時を判断するために参照カウントを実装する必要があります。 フレームワークはドライバーの代わりにオブジェクト参照を追跡するため、UMDF 2 ドライバーは参照をカウントする必要はありません。
UMDF 2 では、各フレームワーク オブジェクトには既定の親オブジェクトがあります。 親オブジェクトが削除されると、フレームワークは関連付けられている子オブジェクトを削除します。 ドライバーが WdfDeviceCreate などのオブジェクト作成メソッドを呼び出すときは、既定の親を受け入れるか、WDF_OBJECT_ATTRIBUTES 構造体でカスタム親を指定できます。 フレームワーク オブジェクトとその既定の親オブジェクトの一覧については、「フレームワーク オブジェクトの概要」を参照してください。
ドライバーの初期化
UMDF 1 ドライバーは、IDriverEntry インターフェイスを実装します。 IDriverEntry::OnDeviceAdd コールバック メソッドでは、通常、ドライバーは次のようになります:
- デバイス コールバック オブジェクトのインスタンスを作成して初期化します。
- IWDFDriver::CreateDevice を呼び出して、新しいフレームワーク デバイス オブジェクトを作成します。
- デバイスのキューとそれに対応するコールバック オブジェクトを設定します。
- IWDFDevice::CreateDeviceInterface を呼び出して、デバイス インターフェイス クラスのインスタンスを作成します。
UMDF 2 ドライバーは、DriverEntry と EvtDriverDeviceAdd を実装します。 その DriverEntry ルーチンでは、UMDF 2 ドライバーは通常、ドライバーの WDF_DRIVER_CONFIG 構造体を初期化する WDF_DRIVER_CONFIG_INIT を呼び出します。 次に、この構造体を WdfDriverCreate に渡します。
その EvtDriverDeviceAdd 関数では、ドライバーが次の操作を行う場合があります:
- デバイス オブジェクトの作成に使用される情報を提供するWDFDEVICE_INIT 構造に入力します。 WDFDEVICE_INITの使用の詳細については、Creating a Framework Device Objectをご参照ください。
- デバイス オブジェクトのコンテキスト領域を設定します。 フレームワーク オブジェクトのコンテキストエリアの割り当てとアクセスの詳細については、Framework Object Context Spaceをご参照ください。
- デバイス オブジェクトを作成します。
- デバイス オブジェクトの要求ハンドラーを指定します。
- I/Oキューを作成します。
- デバイス インターフェイスを作成します。
- デバイス オブジェクトが電源ポリシーを所有している場合は、デバイス アイドル ポリシーとウェイク設定を設定します。
- ハードウェアが割り込みをサポートしている場合は、割り込みオブジェクトを作成します。
ドライバーのインストール
Visual Studio で新しいドライバー プロジェクトを作成すると、新しいプロジェクトに .inx ファイルが含まれます。 ドライバーをビルドすると、Visual Studio によって .inx ファイルが、ドライバー パッケージの一部として使用できる INF ファイルにコンパイルされます。
UMDF 1 ドライバーの INF ファイルにはドライバー クラス ID を含める必要があります。UMDF 2 ドライバーの INF ファイルには DriverCLSID は必要ありません。
また、UMDF 1 ドライバーは INF ファイルで共同インストーラーを参照する必要がありますが、UMDF 2 INF ファイルでは共同インストーラー参照は必要ありません。 UMDF 2 ドライバーの INF ファイルに共同インストーラー参照を表示することはできますが、必須ではありません。
デバイス コンテキストの格納
UMDF 1 では、ドライバーは通常、デバイス コールバック オブジェクト クラスのプライベート メンバーを指定するなどして、ドライバーによって作成されたコールバック オブジェクトにデバイス コンテキストを格納します。 または、UMDF 1 ドライバーは、フレームワーク オブジェクトにコンテキストを登録する IWDFObject::AssignContext メソッドを呼び出すことができます。
UMDF 2 では、フレームワークは、オブジェクト作成メソッドを呼び出すときにドライバーが提供する省略可能な WDF_OBJECT_ATTRIBUTES 構造体に基づいてコンテキスト領域を割り当てます。 オブジェクトの作成メソッドを呼び出した後、ドライバーは WdfObjectAllocateContext を 1 回以上呼び出して、特定のオブジェクトに追加のコンテキスト領域を割り当てることができます。 UMDF 2 ドライバーがコンテキスト構造とアクセサー メソッドを定義するために使用する必要がある手順については、「フレームワーク オブジェクトのコンテキスト領域」を参照してください。
ドライバーのデバッグ
UMDF 2 ドライバーをデバッグするには、Wudfext.dll ではなく、Wdfkd.dll で拡張機能を使用します。 Wudfext.dll の拡張機能の詳細については、「Wdfkd.dll のデバッガー拡張機能の概要」を参照してください。
UMDF 2 では、「KMDF ドライバーと UMDF 2 ドライバーでのインフライト トレース レコーダーの使用」の説明に従って、インフライト トレース レコーダー (IFR) を介して追加のドライバー デバッグ情報を取得することもできます。 また、フレームワーク独自 のインフライト レコーダー (IFR) を使用することもできます。 「フレームワークのイベント ロガーの使用」を参照してください。