次の方法で共有


IRP_MN_QUERY_DEVICE_RELATIONS

PnP マネージャーは、デバイス間の特定の関係を決定するために、この要求を送信します。 次の種類のドライバーがこの要求を処理します。

  • バス ドライバーは、アダプターまたはコントローラー (バス FDO) の BusRelations 要求を処理する必要があります。 フィルター ドライバーは 、BusRelations 要求を 処理する場合があります。

  • バス ドライバーは、子デバイス (子 PDO) の TargetDeviceRelation 要求を処理する必要があります。

  • 関数ドライバーとフィルター ドライバーは 、RemovalRelations および PowerRelations 要求を 処理する場合があります。

  • バス ドライバーは、子デバイス (子 PDO) に対するのようになります。

価値

0x07

主要なコード

IRP_MJ_PNP

送信時

PnP マネージャーは、指定されたデバイスとの関係を持つデバイスに関する情報を収集するには、この IRP を送信します。

PnP マネージャーは、デバイスが列挙されている場合や、デバイスがアクティブな間にデバイスの BusRelations (子デバイス) を照会します。たとえば、ドライバーが IoInvalidateDeviceRelations ルーチンを呼び出して、子デバイスが到着または出発したことを示す場合などです。

PnP マネージャーは、デバイスのドライバーを削除する前に、デバイスの RemovalRelations を照会します。 PnP マネージャーは、デバイスを取り出す前に 、RemovalRelationsEjectRelations を照会します。

PnP マネージャーは、ドライバーまたはユーザー モード アプリケーションがデバイス上の EventCategoryTargetDeviceChange の PnP 通知を登録するときに、デバイスの TargetDeviceRelation を照会します。 PnP マネージャーは、特定のファイル オブジェクトに関連付けられているデバイスを照会します。 IRP_MN_QUERY_DEVICE_RELATIONS は、有効なファイル オブジェクト パラメーターを持つ唯一の PnP IRP です。 ドライバーは、 TargetDeviceRelation のデバイス スタックに対してクエリを実行できます。 ドライバーは、 TargetDeviceRelation クエリを送信するときにファイル オブジェクトを指定する必要はありません。

PnP マネージャーは、デバイスのドライバーが IoInvalidateDeviceRelations を呼び出すと、デバイスの PowerRelations に対してクエリを実行し、このデバイスが暗黙的な電源管理関係を持つデバイスのセットが変更されたことを示します。 PowerRelations 要求は、Windows 7 以降でサポートされています。

BusRelationsRemovalRelationsおよび PowerRelations 要求の場合、PnP マネージャーは、システム スレッドのコンテキストで IRQL = PASSIVE_LEVELでIRP_MN_QUERY_DEVICE_RELATIONSを送信します。

TargetDeviceRelation 要求の場合、PnP マネージャーは IRQL = 任意のスレッド コンテキストでPASSIVE_LEVELでこの IRP を送信します。

入力パラメーター

IO_STACK_LOCATION構造体の Parameters.QueryDeviceRelations.Type メンバーは、クエリ対象のリレーションの種類を指定します。 指定できる値は、 BusRelationsRemovalRelationsRemovalRelationsTargetDeviceRelationPowerRelations です。

現在のIO_STACK_LOCATION構造体の FileObject メンバーは、Parameters.QueryDeviceRelations.TypeTargetDeviceRelation の場合にのみ有効なファイル オブジェクトを指します。

出力パラメーター

I/O 状態ブロックで返されます。

I/O 状態ブロック

ドライバーは 、Irp->IoStatus.Status をSTATUS_SUCCESSまたはSTATUS_INSUFFICIENT_RESOURCESなどのエラー状態に設定します。

成功した場合、ドライバーは Irp->IoStatus.Information を、要求されたリレーション情報を指すPDEVICE_RELATIONS ポインターに設定します。 DEVICE_RELATIONS構造体は次のように定義されます。

typedef struct _DEVICE_RELATIONS {
  ULONG  Count;
  PDEVICE_OBJECT  Objects[1];  // variable length
} DEVICE_RELATIONS, *PDEVICE_RELATIONS;

操作

ドライバーがこの IRP_MN_QUERY_DEVICE_RELATIONSに応答して関係を返す場合、ドライバーは、カウントとデバイス オブジェクト ポインターの適切な数を含むページングされたメモリから DEVICE_RELATIONS 構造体を割り当てます。 PnP マネージャーは、不要になったときに構造体を解放します。 ドライバーが別のドライバーが割り当てた DEVICE_RELATIONS 構造体を置き換える場合、ドライバーは前の構造体を解放する必要があります。

ドライバーは、この IRP (ObReferenceObject) で報告するすべてのデバイスの PDO を参照する必要があります。 PnP マネージャーは、必要に応じて参照を削除します。

関数またはフィルター ドライバーは、デバイスの AddDevice ルーチンが完了した後、デバイスのこの IRP を処理するために準備する必要があります。 バス ドライバーは、デバイスが列挙された直後に BusRelations のクエリを処理するように準備する必要があります。

プラグ アンド プレイのマイナー IRP の処理に関する一般的な規則については、「プラグ アンド プレイ」を参照してください。

次のサブセクションでは、さまざまなクエリを処理するための特定のアクションについて説明します。

BusRelations 要求

PnP マネージャーがアダプターまたはコントローラーのバス関係 (子デバイス) を照会する場合、バス ドライバーは、バス上に物理的に存在するすべてのデバイスの PDO へのポインターの一覧を返す必要があります。 バス ドライバーは、起動されているかどうかに関係なく、すべてのデバイスを報告します。 バス ドライバーは、どの子が存在するかを判断するために、バス デバイスの電源を入れる必要がある場合があります。

警告 PnP マネージャーがそのオブジェクトのデバイス ノード (devnode) を作成するまで、PDO を引数として受け取るルーチンにデバイス オブジェクトを渡すことはできません。 (ドライバーがデバイス オブジェクトを渡した場合、システムは バグ チェック 0xCA: PNP_DETECTED_FATAL_ERROR) でバグ チェックを行います。PnP マネージャーは、 IRP_MN_QUERY_DEVICE_RELATIONS 要求に応答して devnode を作成します。 ドライバーは、PDO の devnode がIRP_MN_QUERY_RESOURCE_REQUIREMENTS要求を受信したときに作成されていることを安全 想定できます。

この IRP に応答するバス ドライバーは、アダプターまたはコントローラーが接続されているバスの親バス ドライバーではなく、バス アダプターまたはコントローラーのファンクション ドライバーです。 バス以外のデバイスの関数ドライバーは、このクエリを処理しません。 このようなドライバーは、次の下位ドライバーに IRP を渡すだけです。 (次の図を参照してください)。フィルター ドライバーは通常、このクエリを処理しません。

Windows Vista 以降のオペレーティング システムでは、ドライバーは常に IRP_MN_QUERY_DEVICE_RELATIONS IRP をペンディングし、後でその処理を完了することをお勧めします。 この順序により、システムはバス関係クエリを非同期的に処理できます。 (Windows Vista より前のオペレーティング システムでは、ドライバーはディスパッチ ルーチンからSTATUS_PENDINGを安全に返すことができますが、PnP マネージャーはバス関係クエリを他の操作と重複させません)。

次の図は、ドライバーがバス関係のクエリを処理する方法を示しています。

バス関係のクエリを処理するドライバーを示す図。

図に示す例では、PnP マネージャーは、USB ハブ デバイスのドライバーに BusRelationsIRP_MN_QUERY_DEVICE_RELATIONSを送信します。 PnP マネージャーは、ハブ デバイスの子の一覧を要求しています。

  1. すべての PnP IRP と同様に、PnP マネージャーは、デバイスのデバイス スタックの最上位のドライバーに IRP を送信します。

  2. オプションのフィルター ドライバーは、スタック内の最上位のドライバーである可能性があります。 フィルター ドライバーは、通常、この IRP を処理しません。IRP をスタックに渡します。 フィルター ドライバーは、たとえば、ドライバーがバス上の列挙不可能なデバイスを公開する場合、この IRP を処理する可能性があります。

  3. USB ハブ バス ドライバーは、IRP を処理します。

    USB ハブ バス ドライバー:

    • まだ存在しない子デバイスの PDO を作成します。

    • バスに存在しなくなったデバイスに対して PDO を非アクティブとしてマークします。 バス ドライバーは、このような PDO を削除しません。PDO を削除するタイミングの詳細については、「 デバイスの削除」を参照してください。

    • バス上に存在するすべての子デバイスを報告します。

      各子デバイスについて、バス ドライバーは PDO を参照し、DEVICE_RELATIONS構造体の PDO へのポインターを配置します。

      この例には、ジョイスティック デバイス用とキーボード デバイス用の 2 つの PDO があります。

      バス ドライバーは、別のドライバーがこの IRP のDEVICE_RELATIONS構造を既に作成しているかどうかを確認する必要があります。 その場合、バス ドライバーは既存の情報に追加する必要があります。

      バスに子デバイスが存在しない場合、ドライバーは、DEVICE_RELATIONS構造体でカウントを 0 に設定し、成功を返します。

    • I/O 状態ブロック内の適切な値を設定し、IRP を次の下位ドライバーに渡します。 アダプターまたはコントローラーのバス ドライバーが IRP を完了しません。

  4. 省略可能な下位フィルター (存在する場合) は、通常、この IRP を処理しません。 このようなフィルター ドライバーは、スタックの下に IRP を渡します。 下位フィルター ドライバーがこの IRP を処理する場合は、子デバイスの一覧に PDO を追加できますが、他のドライバーによって作成された PDO を削除することはできません。

  5. 親バス ドライバーは、デバイス スタック内の唯一のドライバー (デバイスが未加工モード) でない限り、この IRP を処理しません。 すべての PnP IRP と同様に、親バス ドライバーは IoCompleteRequest で IRP を完了します。

    デバイス スタックに 1 つ以上のバス フィルター ドライバーがある場合、このようなドライバーは、バス ドライバーへの途中で IRP を処理したり、デバイス スタックをバックアップする IRP の方法で ( IoCompletion ルーチンがある場合) 可能性があります。 PnP IRP の規則に従って、このようなドライバーは、スタックを下る途中で IRP に PDO を追加したり、スタックをバックアップする IRP の方法 ( IoCompletion ルーチンで) の関係リストを変更したりできます。

エジェトレーション要求

ドライバーは、指定したデバイスが取り出されたときにシステムから物理的に削除される可能性があるデバイスの PDO へのポインターを返します。 デバイスの子の PDO を報告しないでください。PnP マネージャーは常に、親デバイスの前に子デバイスを削除するよう要求します。

PnP マネージャーは、取り出されているデバイスに IRP_MN_EJECT IRP を送信します。 このようなデバイスのドライバーは、IRP の削除も受け取ります。 デバイスの出力関係は、( IRP_MN_EJECT IRP ではなく) IRP_MN_REMOVE_DEVICE IRP を受け取ります。

親バス ドライバーのみが、その子デバイスの 1 つに対して 、DirectiveRelations クエリに応答できます。 関数ドライバーとフィルター ドライバーは、デバイス スタック内の次の下位ドライバーに渡す必要があります。 バス ドライバーは、アダプターまたはコント ローラーの関数ドライバーとしてこの IRP を受け取る場合、バス ドライバーは、関数ドライバーのタスクを実行し、次の下位ドライバーに IRP を渡す必要があります。

PowerRelations 要求

Windows 7 以降では、 PowerRelations クエリを使用すると、ドライバーは、PnP 列挙をサポートする親バスと、バス上の列挙子デバイスとの間の従来のリレーションシップの外部で電源管理関係を指定できます。 たとえば、バス ドライバーがバス上の子デバイスを列挙できない場合、またはデバイスが複数のバスの子である場合、 PowerRelations クエリでは、子デバイスとバスまたはバスの電源関係を記述できます。

PnP マネージャーは、デバイスのドライバーが IoInvalidateDeviceRelations ルーチンを呼び出し、PowerRelationsパラメーター値を指定するときに、デバイスの PowerRelations クエリを発行します。

このクエリに応答して、ターゲット デバイス (つまり、クエリのターゲットであるデバイス) のドライバーは、ターゲット デバイスがオンになる前に電源マネージャーによってオンにする必要がある他のデバイスの PDO へのポインターを含む DEVICE_RELATIONS構造を 提供します。 逆に、これらの他のデバイスは、ターゲット デバイスをオフにした後でのみオフにする必要があります。 電源マネージャーは、クエリの情報を使用して、これらのデバイスが正しい順序でオンまたはオフになっていることを保証します。

この順序付け保証は、S1、S2、S3 (スリープ)、S4 (休止状態)、および S5 (シャットダウン) システムの電源状態との間の遷移を含む、グローバル なシステム スリープ状態遷移にのみ適用されます。 PowerRelations の順序付け保証は、ダイレクト ランタイム電源管理 (DFx) 遷移の場合を除き、システムが S0 (実行中) のシステム状態のままである間、Dx デバイスの電源状態遷移には適用されません。

ターゲット デバイスが特殊なファイル (ページング ファイル、休止状態ファイル、クラッシュ ダンプ ファイルなど) のデバイス パス上にある場合、ターゲット デバイスのドライバーは、InPathTRUE であるIRP_MN_DEVICE_USAGE_NOTIFICATION IRP を処理するときに追加の手順を実行する必要があります。 このドライバーは、 PowerRelations クエリ用に PDO が提供されているデバイスが、特殊なファイルのデバイス パス内であることもサポートできることを確認する必要があります。 このサポートを確認するには、ターゲット デバイスのドライバーは、最初にこれらの各デバイスに IRP_MN_DEVICE_USAGE_NOTIFICATION IRP を送信する必要があり、この IRP は、ターゲット デバイスと同じ UsageNotification.Type を指定する必要があります。 この IRP を受け取るすべてのデバイスが成功状態コードで IRP を完了した場合にのみ、ターゲット デバイスのドライバーは 、そのIRP_MN_DEVICE_USAGE_NOTIFICATION IRP を正常に完了できます。 それ以外の場合、このドライバーは、エラー状態コードでこの IRP を完了する必要があります。

この同じドライバーが InPathFALSE であるIRP_MN_DEVICE_USAGE_NOTIFICATION IRP を処理する場合、ドライバーは、InPathTRUE の場合と同じ一連の依存デバイスにIRP_MN_DEVICE_USAGE_NOTIFICATION IRP を送信する必要があります。 ただし、 InPathFALSE の場合、ドライバーはエラー状態コードでこの IRP を完了しないでください。

PowerRelations クエリに応答するドライバーは、PowerRelations クエリに PDO が提供されているすべてのデバイスでターゲット デバイス変更通知に登録する必要があります。 これらの通知に登録するために、ドライバーは IoRegisterPlugPlayNotification ルーチンを呼び出し、EventCategoryTargetDeviceChangeEventCategory パラメーター値を指定できます。

RemovalRelations 要求

ドライバーは、指定したデバイスのドライバーが削除されたときにドライバーを削除する必要があるすべてのデバイスの PDO へのポインターを返します。 デバイスの子の PDO を報告しないでください。PnP マネージャーは、デバイスを削除する前に、子デバイスの削除を既に要求しています。

削除関係が削除される順序は未定義です。

デバイス スタック内のすべてのドライバーは、この種類のリレーション クエリを処理できます。 関数またはフィルター ドライバーは、次の下位ドライバーに渡す前に IRP を処理します。 バス ドライバーは、IRP を処理し、完了します。

TargetDeviceRelation 要求

TargetDeviceRelation クエリを使用すると、PnP マネージャーは、ハードウェアを制御する PnP デバイス スタック内の PDO の PnP 以外のデバイス スタックに対してクエリを実行できます。

一般に、 ドライバーは、 IRP が特定のデバイス スタックの下部に到達するまで、IRP_MN_QUERY_DEVICE_RELATIONS IRP をスタックに転送します。 PnP 以外のスタックの下部にあるドライバーは、関連する PnP スタックに IRP を転送または再発行します。 たとえば、PnP マネージャーは、PnP 以外のスタックであるファイル システム スタックの上部にあるデバイス オブジェクトに TargetDeviceRelation クエリを送信できます。 ファイル システム スタック内の各デバイス オブジェクトは、クエリがスタックの下部にあるデバイス オブジェクトに到達するまで、その下のデバイス オブジェクトにクエリを渡します。 スタック内の最下位のデバイス オブジェクトは、PnP ストレージ ボリューム スタックの上部にあるデバイス オブジェクトに TargetDeviceRelation クエリを転送または再発行し、その後、クエリはストレージ ボリューム スタックの下部にある PDO に渡されます。

次の一覧は、PnP デバイス スタックの下部にある PDO へのポインターを安全に取得できる状況をまとめたものです。

  • PnP のデバイス オブジェクト

    PnP デバイス スタック内のデバイス オブジェクトは、デバイスの AddDevice ルーチンが呼び出されたときに、スタックの PDO について学習します。 ドライバーは、ポインターの使用が、ロックの削除ルーチンを使用して受信 IRP_MN_REMOVE_DEVICE メッセージと正しく同期されている場合は、PDO へのポインターを安全にキャッシュできます。

  • スタックの一番下ではなく、PnP 以外のスタック内のデバイス オブジェクト

    PnP 以外のスタックの下部にないデバイス オブジェクトの場合、ドライバーは TargetDeviceRelation クエリを送信して、対応する PnP デバイス スタックの下部にある PDO へのポインターを取得できます。

  • デバイスのファイル オブジェクト

    デバイスのファイル オブジェクトを指定すると、ドライバーは IoGetRelatedDeviceObject を呼び出してデバイス オブジェクトを取得し、前のリスト項目の指示に従うことができます。

  • デバイス オブジェクトへのハンドル

    デバイス オブジェクトへのハンドルを指定すると、ドライバーは ObReferenceObjectByHandle を呼び出してデバイスのファイル オブジェクトを取得し、前のリスト項目の指示に従うことができます。

親バス ドライバーは、その子デバイスの TargetDeviceRelation リレーション クエリを処理する必要があります。 バス ドライバーは 、ObReferenceObject を使用して子デバイスの PDO を参照し、 DEVICE_RELATIONS 構造体の PDO へのポインターを返します。 この関係型の構造体には、1 つの PDO ポインターしかありません。 PnP マネージャーは、ドライバーまたはアプリケーションがデバイス上の通知の登録を解除するときに、PDO への参照を削除します。

親バス ドライバーのみが TargetDeviceRelation クエリに応答します。 関数ドライバーとフィルター ドライバーは、デバイス スタック内の次の下位ドライバーに渡す必要があります。 バス ドライバーは、アダプターまたはコント ローラーの関数ドライバーとしてこの IRP を受け取る場合、バス ドライバーは、関数ドライバーのタスクを実行し、次の下位ドライバーに IRP を渡す必要があります。

ドライバーが PDO ベースのスタックにない場合、ドライバーは、ドライバーが I/O を実行するファイル ハンドルに関連付けられているデバイス オブジェクトに新しいターゲット とデバイス関係のクエリ IRP を送信します。

この IRP の送信

ドライバーは、BusRelations を要求するIRP_MN_QUERY_DEVICE_RELATIONSを送信できません。 ドライバーは 、RemovalRelations または DirectiveRelations に対してこの IRP を送信することは制限されませんが、ドライバーが送信する可能性は高くはありません。

ドライバーは、 TargetDeviceRelation のデバイス スタックに対してクエリを実行できます。 IRP の送信については、 IRP の処理 を参照してください。 次の手順は、この IRP に特に適用されます。

  • IRP の次の I/O スタックの場所の値を設定します。 MajorFunctionIRP_MJ_PNPに設定し、 MinorFunctionIRP_MN_QUERY_DEVICE_RELATIONSに設定し、 Parameters.QueryDeviceRelations.Typeを TargetDeviceRelation に設定し、 Irp->FileObject を有効なファイル オブジェクトに設定します。

  • IoStatus.Status をSTATUS_NOT_SUPPORTEDに初期化します。

ドライバーがこの IRP を送信して、ドライバーが受け取った TargetDeviceRelationIRP_MN_QUERY_DEVICE_RELATIONSに応答して PDO を報告した場合、ドライバーは PDO を報告し、IRP が完了したときに返される関係構造を解放します。 ドライバーが別の理由でこの IRP を開始した場合、IRP が完了し、不要になったときに PDO を逆参照するときに、ドライバーは関係構造を解放します。

必要条件

ヘッダ

Wdm.h (Wdm.h、Ntddk.h、または Ntifs.h を含む)

こちらもご覧ください

AddDevice

IoCompleteRequest の

IoGetRelatedDeviceObject

IoInvalidateDeviceRelations

IoRegisterPlugPlayNotification

IRP_MJ_PNP

IRP_MN_DEVICE_USAGE_NOTIFICATION

IRP_MN_EJECT

IRP_MN_QUERY_RESOURCE_REQUIREMENTS

IRP_MN_REMOVE_DEVICE

IO_STACK_LOCATION

ObReferenceObject

ObReferenceObjectByHandle