ドライバー内での IOCTL 要求の作成

クラス ドライバーまたは他の上位レベルのドライバーは、I/O 制御要求に対して IRP を割り当て、次に示す下位ドライバーに送信できます。

  1. 主要な関数コードを使用して I/O 要求パケット (IRP) を割り当てるIRP_MJ_DEVICE_CONTROLまたはIRP_MJ_INTERNAL_DEVICE_CONTROLIoBuildDeviceIoControlRequest ルーチンを使用して、IOCTL IRP を具体的に割り当てできます。 また、IoAllocateIrpIoReuseIrpIoInitializeIrp などの汎用 IRP の作成および初期化ルーチンを使用できます。 IRP の割り当ての詳細については、「 Creating IRP for Lower-Level Drivers」を参照してください

  2. IRP の下位ドライバーの I/O スタックの場所を、IOCTL_XXX コードと適切なパラメーターを使用して設定します。

  3. IOCTL 要求を非同期的に完了する場合は、 KeInitializeEvent ルーチンを呼び出して、イベント オブジェクトを通知イベントとして初期化します。 ドライバーは、このイベントを使用して、I/O 操作が完了するまで待機します。

  4. IRP で IoSetCompletionRoutine を呼び出して、必要に応じて上位ドライバーが IoCompletion ルーチンを指定して、次の操作を行います。

  5. IoCallDriver を呼び出して、下位ドライバーに要求を渡します。

  6. IoCallDriver から STATUS_PENDING場合は、KeWaitForSingleObject ルーチンを呼び出して、現在のスレッドを待機状態に設定します。 ドライバーは、ルーチンの Object パラメーターを 、KeInitializeEvent の呼び出しで初期化されたイベント オブジェクトのアドレスに設定します。

    メモドライバーが Timeout パラメーターを NULL に設定するか、0 以外の値を含む変数のアドレスに設定して KeWaitForSingleObject を呼び出す場合、ドライバーは非ビットスレッド コンテキストで IRQL <= APC_LEVEL で実行されている必要があります。 それ以外の場合、ドライバーは IRQL <= DISPATCH_LEVEL で実行されている必要があります。

イベントは、IOCTL 要求が 完了すると、その IoCompletion ルーチンによってシグナル化されます。 イベントがシグナル状態にされると、スレッドは実行を再開します。

大事なドライバーがイベント オブジェクトをスタックのローカル変数として割り当てる場合、ドライバーは WaitMode パラメーターを KernelMode に設定して KeWaitForSingleObject を呼び出す必要があります。 このパラメーター値を使用すると、スタックがページアウトされません。

同期の問題やアクセス違反の可能性を回避するために、I/O 制御コードのパラメーターに埋め込みポインターが含まれるのはめったにありません。 特定の SCSI 要求を除き、Irp-AssociatedIrp> のバッファー。SystemBufferIrp-MdlAddress>、および at ParametersDeviceIoControl。ドライバーの I/O スタックの場所にある Type3InputBuffer には、他のデータ バッファーへのポインターが含まれているのではなく、システム定義の I/O 制御コードのポインターを含む構造体も含め "しません"。 I/O 制御コードを含む IRP でデータ バッファーを使用する方法の詳細については、「I/O 制御コードのバッファーの説明 」を参照してください

それでも、内部 I/O 制御コードを定義するクラス/ポート ドライバーのペアは、上位レベルのドライバーから下位レベルのドライバーにドライバー割り当てメモリへの埋め込みポインターを渡す可能性があります。 このようなクラス/ポート ドライバーのペアは、次の条件を満たします。

  • 一度に 1 つのドライバーだけがデータにアクセスできます。

  • プライベート データ バッファーには、ポート ドライバーによって任意のスレッド コンテキストでアクセスできます。

ディスプレイ ドライバーは、GDI 関数 EngDeviceIoControl を呼び出して、システム ビデオ ポート ドライバーを介して、プライベートに定義されたデバイス固有の I/O 制御要求とシステム定義のパブリック I/O 制御要求を、対応するアダプター固有のビデオ ミニポート ドライバーに送信できます。

ドライバー パッケージのユーザー モード コンポーネントは、 DeviceIoControl を呼び出して、I/O 制御要求をドライバー スタックに送信できます。 I/O マネージャーは、要求 IRP_MJ_DEVICE_CONTROLを作成 し、それを最高レベルのドライバーに配信します。