下のデバイス スタックへの PnP IRP の受け渡し
PnP マネージャーは IRP を使用して、デバイスを起動、停止、削除すること、およびドライバーのデバイスに関してドライバーにクエリを実行することをドライバーに指示します。 すべての PnP IRP には主要な関数コード IRP_MJ_PNP があるので、すべての PnP ドライバーは、この関数コードを扱う DispatchPnP ルーチンを提供する必要があります。 PnP マネージャーは、IRP を送信するときに Irp->IoStatus.Status を STATUS_NOT_SUPPORTEDに初期化します。 詳細については「DispatchPnP ルーチン」を参照してください。
PnP マイナー IRP の一覧については「プラグ アンド プレイのマイナー IRP」を参照してください。
デバイスのすべてのドライバーには、スタックでドライバーが IRP の処理に失敗しない限り、PnP IRP に応答する機会を用意する必要があります (次の図を参照してください)。
デバイスのドライバーのうち、PnP IRP に応答するドライバーが 1 つのみであると想定することはできません。 たとえば、IRP_MN_QUERY_CAPABILITIES 要求に応答して、次の下位ドライバーに渡すことなく IRP を完了するファンクション ドライバーがあるとします。 この場合は、下位ドライバーでサポートされている機能が報告されません。このような機能として、親バス ドライバーでサポートされている一意のインスタンス ID や電源管理機能などがあります。
親バス ドライバーが IoCompleteRequest を呼び出し、I/O マネージャーがファンクション ドライバーまたはフィルター ドライバーによって登録されている IoCompletion ルーチンを呼び出すと、PnP IRP はデバイス スタックを上位方向へ戻ります。
ファンクション ドライバーやフィルター ドライバーは、PnP IRP を受信したときに次の処理を実行する必要があります。
- ドライバーが IRP に応答してアクションを実行する場合:
- 適切なアクションを実行します。
- Irp->IoStatus.Status を、STATUS_SUCCESS などの適切な状態に設定します。 Irp->IoStatus.Information を、IRP に適切であれば設定します。
- IoSkipCurrentIrpStackLocation または IoCopyCurrentIrpStackLocationToNext を使用して、次のスタックの場所を設定します。 IoCompletion ルーチンを設定している場合は後者のルーチンを呼び出します。
- 必要に応じて IoCompletion ルーチンを設定します。
- IRP を完了しないでください (IoCompleteRequest を呼び出さないようにします)。IRP は親バス ドライバーによって完了します。
- この IRP に対してドライバーがアクションを実行しない場合、そのドライバーは次のドライバーに IRP を渡す準備します。
- IoSkipCurrentIrpStackLocation を呼び出して、ドライバーのスタックの場所を IRP から削除します。
- Irp->IoStatus ではどのフィールドも設定しないでください。
- IoCompletion ルーチンを設定しないでください。
- IRP を完了しないでください (IoCompleteRequest を呼び出さないようにします)。IRP は親バス ドライバーによって完了します。
ファンクション ドライバーまたはフィルター ドライバーが IRP の処理に失敗しなかった場合、そのドライバーは IoCallDriver を使用して次の下位ドライバーに IRP を渡します。 ドライバーには次の下位ドライバーへのポインターがあります。そのポインターは、上位ドライバーの AddDevice ルーチンで IoAttachDeviceToDeviceStack を呼び出すことによって返されます。
親バス ドライバーは、IRP に応答するあらゆるタスクを実行した後で IRP を完了します。 バス ドライバーが IoCompleteRequest を呼び出した後、I/O マネージャーは、デバイスのファンクション ドライバーまたはフィルター ドライバーによって登録されたすべての IoCompletion ルーチンを呼び出します。