SCIENCE PARK

デバドラ講座

【 デバドラ講座24 : ディスパッチルーチンの概要 】

ディスパッチルーチンはアプリケーションからのデバイスに対する要求を処理します。階層ドライバの場合、最上位のドライバのディスパッチルーチンはユーザーモードのアプリケーションのI/O要求を直接処理します。その下の中間ドライバや物理ドライバのディスパッチルーチンは一つ上のドライバからのI/O要求を処理します。I/O処理要求があった際、ディスパッチルーチンはI/Oマネージャによって呼び出されます。どのディスパッチルーチンを呼ぶかは、I/Oメジャー機能コードによって管理されています。また、ディスパッチルーチンはドライバエントリ処理が終了してから呼び出されます。

ディスパッチルーチンは次のようなエントリポイントの形式になっています。

NTSTATUS Dispatchxxxx(
IN PDEVICE_OBJECT               DeviceObject,
IN PIRP                   Irp)
DeviceObject:
ドライバエントリ処理で作成されたデバイスオブジェクト(FDO)のポインタです。
Irp:
実行されるI/Oリクエストが記述されているI/Oリクエストパケット(IRP)へのポインタです。

DeviceObjectとIrp引数は、ディスパッチルーチンがI/Oマネージャによって呼ばれる際に渡されます。IRPについてはレポート25で詳細を説明します。

1.オープンとクローズディスパッチルーチン

CreateFileとCloseHandle関数を実行する際、I/OマネージャはIRPを作成し、このディスパッチルーチンを呼び出します。このルーチンは直接アプリケーションからアクセスが許されているドライバにのみ存在します。階層ドライバの場合、中間ドライバと物理ドライバにこのルーチンは必要ありません。通常このルーチンは直接ハードウェアにアクセスする必要はありません。

このルーチンはオープンディスパッチルーチンとクローズディスパッチルーチンに分けられることもあります。このルーチンは次のようなエントリポイントの形式になっています。

TSTATUS Bus_CreateClose(
              IN PDEVICE_OBJECT               DeviceObject,
              IN PIRP                   Irp)

2.デバイス操作ディスパッチルーチン

ReadFile, WriteFile, DeviceIoControl関数を実行する際、I/OマネージャはIRPを作成し、このディスパッチルーチンを呼び出します。このルーチンは直接アプリケーションからアクセスが許されているドライバにのみ存在します。階層ドライバの場合、中間ドライバと物理ドライバにこのルーチンは必要ありません。通常このルーチンはHALを通じてハードウェアにアクセスします。

このルーチンはリードディスパッチルーチン、ライトディスパッチルーチン、DeviceIoControlディスパッチルーチンに分けられることもあります。ドライバの設定によって、上記すべてのルーチンが揃わない場合もあります。このルーチンは次のようなエントリポイントの形式になっています。

NTSTATUS Bus_IoCtl(
              IN PDEVICE_OBJECT               DeviceObject,
              IN PIRP                   Irp)

3.シャットダウンディスパッチルーチン

ユーザーがシャットダウンを行う際、ハードウェアを元の状態に戻すためにこのルーチンが呼び出されます。通常このルーチンを設ける必要はありません。このルーチンは次のようなエントリポイントの形式になっています。

NTSTATUS Bus_Shutdown(
              IN PDEVICE_OBJECT               DeviceObject,
              IN PIRP                   Irp)

4.PnPディスパッチルーチン

PnP機能に対応するためのディスパッチルーチンです。PnPマネージャが新しいデバイスを検出した際、I/Oマネージャによってこのルーチンが呼び出されます。このディスパッチルーチンにはPnPに対応するために、数多くのマイナー機能を揃えています。このルーチンは次のようなエントリポイントの形式になっています。

NTSTATUS Bus_PnP(
              IN PDEVICE_OBJECT               DeviceObject,
              IN PIRP                   Irp)

5. Powerディスパッチルーチン

Windows2000/XPの電源管理機能に対応するためのディスパッチルーチンです。Windows2000/XPのドライバには必ずこのルーチンが必要となります。このルーチンは次のようなエントリポイントの形式になっています。

NTSTATUS Bus_Power(
              IN PDEVICE_OBJECT               DeviceObject,
              IN PIRP                   Irp)

6.メジャー機能コード

メジャー機能コードとは、ユーザーからI/O要求があった際、I/Oマネージャがそれぞれの要求に応じて生成した機能コードです。ドライバエントリでは各メジャー関数に対応するディスパッチルーチンの設定を行うことが可能です。メジャー機能コードは全部で30個近くあります。その中でも、次の7つがよく使われます。

              IRP_MJ_CREATE
              IRP_MJ_CLOSE
              IRP_MJ_READ
              IRP_MJ_WRITE
              IRP_MJ_DEVICE_CONTROL
              IRP_MJ_PNP
              IRP_MJ_POWER

7.マイナー機能コード

I/Oマネージャがメジャー機能コードを生成する際、各メジャー機能に属するマイナー機能コードも同時に生成されます。しかし、すべてのメジャー機能にマイナー機能コードが存在するわけではありません。例えば、IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_DEVICE_CONTROLにはマイナー機能コードは存在しません。よく使われるマイナー機能コードはIRP_MJ_PNPとIRP_MJ_POWERに属したものです。

参考資料

「NTドライバプログラミング」
Peter G. Viscarola、W. Anthony Mason著 久保雅俊、三浦秀朗訳 サイエンスパーク株式会社 監修
「WDMデバイスドライバプログラミング完全ガイド」上、下
Edword N. Dekker, Jpseph M. Newcomer著 株式会社クイック訳
page up