ドライバ開発情報
開発20 toaster\busのロードとドライバエントリの解析
デバイスドライバをはじめ、デバイスにかかわるお困りごとの際はお気軽にお問い合わせください。
Driverディレクトリ dispatch.cの解析
オープンクローズルーチン
NTSTATUS XxDispatchOpenClose( |
書き込みルーチン
NTSTATUS XxDispatchWrite( |
Testディレクトリ xxtest.cの解析
VOID __cdecl main(VOID) |
エラーメッセージルーチン
|
「toaster\bus」の解析
Bus_FDO_Powerルーチン(power.c)
NTSTATUS Bus_FDO_Power( PFDO_DEVICE_DATA Data, PIRP Irp // デバイスエクステンションにデータをセットする ) { NTSTATUS status; // 完了ステータス POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; // スタックロケーションのポインタ stack = IoGetCurrentIrpStackLocation(Irp); // 現在のスタックロケーションを取得 powerType = stack->Parameters.Power.Type; // 要求の種類を示す powerState = stack->Parameters.Power.State; // Errorが呼ばれるとデバイススタックからデバイスをデタッチします。また、デバイスオブジェクトを削除します。 if (Data->DevicePnPState == NotStarted) { PoStartNextPowerIrp(Irp); // 次のパワーIRP開始の準備をする IoSkipCurrentIrpStackLocation(Irp); // 現在のスタックロケーションの内容を // 次に低い階層のスタックロケーションにコピーする return PoCallDriver(Data->NextLowerDriver, Irp); // 次に低い階層のスタックロケーションにパワーIRPを受け渡す } Bus_IncIoCount(Data); // デバイスの受け取った要求回数を1増やす if (stack->MinorFunction == IRP_MN_SET_POWER) { // PnPのマイナー機能[IRP_MN_START_DEVICE] デバイス起動時に呼ばれます。 Bus_KdPrint_Cont(Data, BUS_DBG_POWER_TRACE, ("\tRequest to set %s state to %s\n", ((powerType == SystemPowerState) ? "System" : "Device"), ((powerType == SystemPowerState) ? DbgSystemPowerString(powerState.SystemState) : DbgDevicePowerString(powerState.DeviceState)))); } PoStartNextPowerIrp(Irp); // 次のパワーIRP開始の準備をする IoSkipCurrentIrpStackLocation(Irp); // 現在のスタックロケーションの内容を次に // 低い階層のスタックロケーションにコピーする status = PoCallDriver(Data->NextLowerDriver, Irp); // 次に低い階層のスタックロケーションにパワーIRPを受け渡す Bus_DecIoCount(Data); // デバイスの受け取った要求回数を1減らす return status; } |
Bus_IoCtlルーチン(busenum.c)
NTSTATUS Bus_IoCtl( // サブルーチン Bus_StartFdo を呼びます。具体的なスタート処理はこのサブルーチンで処理します。 IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION irpStack; // スタックロケーションのポインタ NTSTATUS status; // 完了ステータス ULONG inlen, outlen; // バイト長 PFDO_DEVICE_DATA fdoData; // デバイスエクステンションのポインタ PVOID buffer; // バッファのポインタ PAGED_CODE(); // このルーチンはページプールメモリで実行します fdoData = (PFDO_DEVICE_DATA)DeviceObject->DeviceExtension; // デバイスオブジェクトからデバイスエクステンションのポインタの取得 // デバイスの停止保留状態から、起動状態に戻します。 if (!fdoData->IsFDO) { status = STATUS_INVALID_DEVICE_REQUEST; // IRPの完了状態はデバイスが無効 Irp->IoStatus.Status = status; // IRPに状態を設定 IoCompleteRequest(Irp, IO_NO_INCREMENT); // IRPの完了を伝える return status; } // デバイスの停止処理を行います。 if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_DELETE_PENDING; // 状態の設定 IoCompleteRequest(Irp, IO_NO_INCREMENT); // IRPの完了 return status; } Bus_IncIoCount(fdoData); // デバイスの受け取った要求回数を1増やす irpStack = IoGetCurrentIrpStackLocation(Irp); // 現在のスタックロケーションを取得 buffer = Irp->AssociatedIrp.SystemBuffer; // システムバッファの取得 inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; // 入力バッファのバイト長を取得 outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; // 出力バッファのバイト長を取得 status = STATUS_INVALID_PARAMETER; // 定義していないコントロールコード switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { // デバイスを削除できるか調べます。 // デバイスの削除保留状態から起動状態に戻します。 case IOCTL_BUSENUM_PLUGIN_HARDWARE: if ((inlen == outlen) && ((sizeof(BUSENUM_PLUGIN_HARDWARE) + sizeof(UNICODE_NULL) * 2) <= inlen) && (sizeof(BUSENUM_PLUGIN_HARDWARE) == ((PBUSENUM_PLUGIN_HARDWARE)buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); // 完了状態を設定 status = Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE)buffer, inlen, fdoData); // メッセージの表示 Irp->IoStatus.Information = outlen; // 読み書きしたバイト長の設定 } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: if ((sizeof(BUSENUM_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); // メッセージの表示 status = Bus_UnPlugDevice((PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); // 完了状態を設定 Irp->IoStatus.Information = outlen; // 読み書きしたバイト長の設定 } break; case IOCTL_BUSENUM_EJECT_HARDWARE: if ((sizeof(BUSENUM_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); // メッセージの表示 status = Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); // 完了状態を設定 Irp->IoStatus.Information = outlen; // 読み書きしたバイト長の設定 } break; default: break; // 突然のデバイス削除が発生した時に呼び出されます。 } Irp->IoStatus.Status = status; // 完了状態を設定 IoCompleteRequest(Irp, IO_NO_INCREMENT); // IRPの完了 Bus_DecIoCount(fdoData); // デバイスの受け取った要求回数を1減少させる return status; } |
参考資料
- 「WDMデバイスドライバプログラミング完全ガイド」下
- Edward N. Dekker, Joseph M. Newcomer著 株式会社クイック訳
- 「Windows NTデバイスドライバプログラミング」
- アート・ベーカー著 WinProgDDK ML和訳プロジェクト訳