UMDF ドライバーでのデバイス インターフェイスの使用

警告

UMDF 2 は UMDF の最新バージョンであり、UMDF 1 よりも優先されます。 すべての新しい UMDF ドライバーは、UMDF 2 を使用して記述する必要があります。 UMDF 1 には新機能が追加されておらず、Windows 10 の新しいバージョンでは UMDF 1 のサポートが制限されています。 ユニバーサル Windows ドライバーでは、UMDF 2 を使用する必要があります。

アーカイブされた UMDF 1 サンプルは、「Windows 11、バージョン 22H2 - 2022 年 5 月 ドライバーサンプルの更新」でご確認いただけます。

詳しくは、「UMDF の概要」をご覧ください。

デバイス インターフェイスとは、アプリケーションがデバイスへのアクセスに使用できるプラグ アンド プレイ (PnP) デバイスへのシンボリック リンクです。 ユーザーモード アプリケーションは、インターフェイスのシンボリック リンク名を、Microsoft Win32 CreateFile 関数などの API 要素に渡すことができます。 デバイス インターフェイスのシンボリック リンク名を取得するために、ユーザー モード アプリケーションは SetupDi 関数を呼び出すことができます。 SetupDi 関数の詳細については、「SetupDi デバイス インターフェイス関数」を参照してください。

各デバイス インターフェイスは、デバイス インターフェイス クラスに属しています。 たとえば、CD-ROM デバイスのドライバー スタックは、GUID_DEVINTERFACE_CDROM クラスに属するインターフェイスを提供する場合があります。 CD-ROM デバイスのドライバーの 1 つは、CD-ROM デバイスが使用可能であることをシステムとアプリケーションに通知するために、GUID_DEVINTERFACE_CDROM クラスのインスタンスを登録します。 デバイス インターフェイス クラスの詳細については、「デバイス インターフェイスの概要」を参照してください。

デバイス インターフェイスの登録

デバイス インターフェイス クラスのインスタンスを登録するために、UMDF ベースのドライバーは IDriverEntry::OnDeviceAdd コールバック関数内から IWDFDevice::CreateDeviceInterface を呼び出すことができます。 ドライバーがインターフェイスの複数のインスタンスをサポートしている場合は、各インスタンスに一意の参照文字列を割り当てることができます。

デバイス インターフェイスの有効化と無効化

作成が成功すると、フレームワークはデバイスの PnP 状態に基づいてインターフェイスを自動的に有効化および無効化します。

さらに、ドライバーは、デバイス インターフェイスを必要に応じて無効にして、再度有効にすることができます。 たとえばドライバーが、デバイスが応答を停止したと判断した場合、ドライバーは IWDFDevice::AssignDeviceInterfaceState を呼び出してデバイスのインターフェイスを無効にし、アプリケーションがインターフェイスへの新しいハンドルを取得できないようにすることができます (インターフェイスに対する既存のハンドルは影響を受けません)。デバイスが後で使用可能になった場合、ドライバーは IWDFDevice::AssignDeviceInterfaceState をもう一度呼び出してインターフェイスを再度有効にすることができます。

デバイス インターフェイスへのアクセス要求の受信

アプリケーションがドライバーのデバイス インターフェイスへのアクセスを要求すると、フレームワークはドライバーの IQueueCallbackCreate::OnCreateFile コールバック関数を呼び出します。 ドライバーは、IWDFFile::RetrieveFileName を呼び出して、アプリケーションがアクセスしているデバイスまたはファイルの名前を取得できます。 ドライバーがデバイス インターフェイスの登録時に参照文字列を指定した場合、オペレーティング システムは IWDFFile::RetrieveFileName が返すファイル名またはデバイス名に参照文字列を含めます。

デバイス イベントの作成

UMDF ベースのドライバーは、IWDFDevice::PostEvent を呼び出すことによって、デバイス固有のカスタム イベント (デバイス イベントと呼ばれます) を作成できます。 デバイスのインターフェイスのいずれかを使用するように登録されているドライバーは、デバイスのカスタム イベントの通知を受け取ることができます。 UMDF ベースのドライバーは、IRemoteInterfaceCallbackEvent::OnRemoteInterfaceEvent コールバック関数を提供することで、このような通知を受け取ります。

カスタム イベントはデバイスに固有です。 イベントを作成するドライバーの開発者と、イベントを受け取るドライバーの開発者の両方が、イベントの意味を理解する必要があります。

別のドライバーのデバイス インターフェイスへのアクセス

UMDF ベースのドライバーで、別のドライバーが提供するデバイス インターフェイスに I/O 要求を送信する場合は、デバイス インターフェイスを表すリモート I/O ターゲットを作成できます。

まず、デバイス インターフェイスが使用可能な場合に通知を受け取るために、ドライバーを登録する必要があります。 次の手順に従います。

  1. ドライバーが IWDFDriver::CreateDevice を呼び出すとき、ドライバーは IPnpCallbackRemoteInterfaceNotification インターフェイスを提供できます。 このインターフェイスの IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival コールバック関数は、デバイス インターフェイスが使用可能になったときにドライバーに通知します。

  2. ドライバーが IWDFDriver::CreateDevice を呼び出した後、ドライバーが使用するデバイス インターフェイスごとに IWDFDevice2::RegisterRemoteInterfaceNotification を呼び出すことができます。

その後、フレームワークは、指定されたデバイス インターフェイスが使用可能になるたびに、ドライバーの IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival コールバック関数を呼び出します。 コールバック関数は、IWDFRemoteInterfaceInitialize::GetInterfaceGuidIWDFRemoteInterfaceInitialize::RetrieveSymbolicLink を呼び出して、どのデバイス インターフェイスが到着したかを判断できます。

ドライバーの IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival コールバック関数は、通常、次のことを行う必要があります。

  1. IWDFDevice2::CreateRemoteInterface を呼び出してリモート インターフェイス オブジェクトを作成し、必要に応じて IRemoteInterfaceCallbackEvent インターフェイスと IRemoteInterfaceCallbackRemoval インターフェイスを提供します。

  2. IWDFDevice2::CreateRemoteTarget を呼び出してリモート ターゲット オブジェクトを作成し、必要に応じて IRemoteTargetCallbackRemoval インターフェイスを提供します。

  3. IWDFRemoteTarget::OpenRemoteInterface を呼び出して、デバイス インターフェイスをリモート ターゲットに接続します。

    デバイス インターフェイスが SWENUM ソフトウェア デバイス列挙子によって作成される場合、ドライバーは作業項目から OpenRemoteInterface を呼び出す必要があります。 (たとえば、Windows SDK の QueueUserWorkItem 関数を参照してください。)

これで、ドライバーは I/O 要求をフォーマットしてリモート I/O ターゲットに送信できるようになりました。

IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival コールバック関数に加えて、UMDF ベースのドライバーは、デバイス インターフェイス イベントの通知を受信する 2 つの追加のコールバック関数を提供できます。