次の方法で共有


DispatchPnP ルーチン

ドライバーの DispatchPnP ルーチンは、IRP_MJ_PNP I/O 関数コードの IRP を処理することによってプラグ アンド プレイをサポートします。 IRP_MJ_PNP関数コードには、いくつかのマイナー I/O 関数コード (プラグ アンド プレイ マイナー IRP を参照) が関連付けられています。その一部には、すべてのドライバーを処理する必要があり、その一部を必要に応じて処理できます。 PnP マネージャーは、これらのマイナー関数コードを使用して、ドライバーを起動、停止、および削除し、デバイスに関するドライバーのクエリを実行します。

デバイスのすべてのドライバーは、機能またはフィルター ドライバーが IRP を失敗することが許可されている場合を除き、デバイスの PnP IRP を処理する機会を持っている必要があります。

各ドライバーの DispatchPnP ルーチンは、次の規則に従う必要があります。

  • 関数またはフィルター ドライバーは、関数またはフィルター ドライバーが IRP を処理し、(リソースが不足しているためなど) エラーが発生しない限り、デバイス スタック内の次のドライバーに PnP IRP を渡す必要があります。

    いずれかのドライバーでエラーが発生しない限り、デバイスのすべてのドライバーは、デバイスの PnP IRP を処理する機会を持っている必要があります。 PnP マネージャーは、デバイス スタック内の最上位のドライバーに Irp を送信します。 関数ドライバーとフィルター ドライバーは、次のドライバーに IRP を渡し、親バス ドライバーは IRP を完了します。 詳細については、 デバイス スタックへの PnP IRP の受け渡 しを参照してください。

    ドライバーは、IRP を処理しようとし、(リソースが不足しているなど) エラーが発生した場合、IRP に失敗する可能性があります。 ドライバーが処理できないコードを含む IRP を受け取った場合、ドライバーは IRP を失敗させてはなりません。 IRP の状態を変更せずに、このような IRP を次のドライバーに渡す必要があります。

  • ドライバーは、特定の PnP IRP を処理する必要があり、必要に応じて他を処理できます。

    各 PnP ドライバーは、 IRP_MN_REMOVE_DEVICEなどの特定の IRP を処理するために必要であり、必要に応じて他の IRP を処理できます。 ドライバー (ファンクション ドライバー、フィルター ドライバー、バス ドライバー) の種類ごとに必要な IRP とオプションについては、「 プラグ アンド プレイマイナー IRP」を参照してください。

    ドライバーは、適切なエラー状態で必要な PnP IRP を失敗させることができますが、このような IRP に対してはステータスSTATUS_NOT_SUPPORTEDを返してはいけません。

  • ドライバーが PnP IRP を正常に処理する場合、ドライバーは IRP の状態を成功に設定します。 状態を設定するためにスタック内の別のドライバーに依存しません。

    ドライバーは、ドライバーが IRP を正常に処理したことを PnP マネージャーに通知するSTATUS_SUCCESSに Irp >IoStatus.Status を設定します。 一部の IRP の場合、バス ドライバー以外のドライバーは、その親バス ドライバーに依存して状態を成功に設定できる場合があります。 ただし、これは危険な方法です。 一貫性と堅牢性のために、ドライバーは、正常に処理する各 PnP IRP の IRP の状態を成功に設定する必要があります。

  • ドライバーが IRP に失敗した場合、ドライバーはエラー状態で IRP を完了し、IRP を次のドライバーに渡しません。

    IRP_MN_QUERY_STOP_DEVICEなどの IRP を失敗させるために、ドライバーは Irp->IoStatus.Status をSTATUS_UNSUCCESSFULに設定します。 他の IRP の追加のエラー状態値には、STATUS_INSUFFICIENT_RESOURCESとSTATUS_INVALID_DEVICE_STATEが含まれます。

    ドライバーは、処理する IRP のSTATUS_NOT_SUPPORTEDを設定しません。 これは、PnP マネージャーによって設定された初期状態です。 この状態で IRP が完了した場合は、スタック内のドライバーが IRP を処理しなかったことを意味します。すべてのドライバーは、次のドライバーに IRP を渡しました。

  • ドライバーは、デバイス スタックを下る IRP を処理するディスパッチ ルーチン、または デバイス スタックを戻る IRP を処理する IoCompletion ルーチン、または IRP の参照ページで指定された両方の方法で PnP IRP を処理する必要があります。

    一部の PnP IRP ( IRP_MN_REMOVE_DEVICE など) は、最初にデバイス スタックの上部にあるドライバーで処理し、次に次に下位のドライバーごとに処理する必要があります。 その他 ( IRP_MN_START_DEVICEなど) は、親バス ドライバーが最初に処理する必要があります。 他の例としては、IRP_MN_QUERY_CAPABILITIESのように、デバイススタックを通じて下降する際と上昇する際の両方で処理できるものがあります。 各 PnP IRP に適用される規則については、「 プラグ アンド プレイマイナー IRP 」を参照してください。 親バス ドライバーで最初に処理する必要がある PnP IRP の処理については、「 下位ドライバーが完了するまで PnP IRP 処理を延期する」を参照してください。

  • ドライバーは、デバイススタックの下のレベルに向かう途中でIRPに情報を追加し、上のレベルに戻る途中で情報を変更または削除する必要があります。

    PnP クエリ IRP に応答して情報を返す場合、ドライバーは、デバイスの階層化されたドライバーによって渡される順序の情報を有効にするには、この規則に従う必要があります。

  • 明示的に文書化されている場合を除き、ドライバーは、特定の順序で送信される PnP IRP に依存してはなりません。

  • ドライバーは、PnP IRP を送信するときに、デバイス スタックの最上位のドライバーに IRP を送信する必要があります。

    ほとんどの PnP IRP は PnP マネージャーによって送信されますが、一部はドライバー ( たとえば、IRP_MN_QUERY_INTERFACE) によって送信できます。 ドライバーは、デバイス スタックの上部にあるドライバーに PnP IRP を送信する必要があります。 IoGetAttachedDeviceReference を呼び出して、デバイス スタックの上部にあるドライバーのデバイス オブジェクトへのポインターを取得します。