ファンクション ドライバーまたはフィルター ドライバー内の AddDevice ルーチン

関数またはフィルター ドライバーの AddDevice ルーチンは、次の手順を実行する必要があります。

  1. IoCreateDevice を呼び出し、追加するデバイスの機能デバイス オブジェクトまたはフィルター デバイス オブジェクト (FDO またはフィルター DO) を作成します。

    PnP マネージャーのセキュリティをバイパスするため、デバイス オブジェクトの DeviceName を指定しないでください。 ユーザー モード コンポーネントにデバイスへのシンボリック リンクが必要な場合は、デバイス インターフェイスを登録します (次の手順を参照)。 カーネル モード コンポーネントにレガシーデバイス名が必要な場合、ドライバーはデバイス オブジェクトに名前を付ける必要がありますが、名前付けはお勧めしません。

    DeviceCharacteristics パラメーターにFILE_DEVICE_Standard Edition CURE_OPENを含めます。 この特性は、I/O マネージャーは相対オープンや末尾のファイル名オープンを含むすべてのオープンな要求に対し、デバイス オブジェクトに対してセキュリティ チェックを実行するように指示します。

  2. [任意] デバイスへのシンボリック リンクを 1 つ以上作成します。

    IoRegisterDeviceInterface を呼び出してデバイス機能を登録し、アプリケーションまたはシステム コンポーネントがデバイスを開くために使用できるシンボリック リンクを作成します。 ドライバーは、 IRP_MN_START_DEVICE 要求を処理する際に IoSetDeviceInterfaceState を呼び出すことによって、インターフェイスを有効にする必要があります。 詳細については「デバイス インターフェイス クラスの概要」を参照してください。

  3. デバイスの PDO へのポインターをデバイス拡張機能に格納します。

    PnP マネージャは、AddDevicePhysicalDeviceObject パラメータとして PDO へのポインタを提供します。 ドライバーは、 IoGetDevicePropertyなどの ルーチンの呼び出しで PDO ポインターを使用します。

  4. デバイス拡張機能でフラグを定義して、デバイスの特定の PnP 状態 (デバイスの一時停止、削除、突然削除など) を追跡します。

    例えば、デバイスが一時停止状態の間に受信 IRP を保持する必要があることを示すフラグを 1 つ定義します。 IRP をキューに格納するためのメカニズムがまだドライバーにない場合は、IRP を保持するためのキューを作成します。 詳細については、 IRPのキューイングとデキューイング を参照してください。

    また、デバイス拡張機能に IO_REMOVE_LOCK 構造を割り当て、 IoInitializeRemoveLock を呼び出してこの構造を初期化します。 詳細については、 ロック解除の使用を参照してください。

  5. デバイス オブジェクトのDO_BUFFERED_IOまたはDO_DIRECT_IO フラグ ビットを設定して、デバイス スタックに送信される I/O 要求に I/O マネージャーが使用するバッファリングの種類を指定します。 最上位レベルのドライバーの場合を除き、スタック内の次の下位ドライバーと同じ値を持つ上位レベルのドライバーまたはこのメンバー。 詳細については「デバイス オブジェクトの初期化」を参照してください。

  6. 必要に応じて、電力管理のDO_POWER_INRUSHまたはDO_POWER_PAGABLE フラグを設定します。 ページング可能なドライバーは、DO_POWER_PAGABLE フラグを設定する必要があります。 デバイス オブジェクト フラグは通常、バス ドライバーがデバイスのPDOを作成するときに設定されます。 ただし上位レベルのドライバーは、場合によっては、FDO またはフィルターの DO を作成するときに AddDevice ルーチンでこれらのフラグの値を変更する必要があります。 詳細については、 電力管理用デバイス オブジェクト フラグの設定 を参照してください。

  7. イベント、スピン ロック、その他のオブジェクトなど、ドライバーがこのデバイスの管理に使用するその他のソフトウェア リソースを作成または初期化します。 (IRP_MN_START_DEVICE 要求への応答として、I/O ポートなどのハードウェア リソースは後で設定されます。)

    AddDevice ルーチンはシステム スレッドのコンテキストで、IRQL = PASSIVE_LEVEL の文脈で実行されるため、システム ページ ファイルを保持するデバイスをドライバーが制御していない限り、 ExAllocatePoolWithTag を使用して初期化時にのみ使用するよう割り当てられたメモリは、ページ プールから取得できます。 このようなメモリ割り当ては、AddDevice が制御を返す前に ExFreePool でリリースする必要があります。

  8. デバイス オブジェクトをデバイス スタックにアタッチします (IoAttachDeviceToDeviceStack)。

    TargetDevice パラメーターで、デバイスの PDO へのポインターを指定します。

    IoAttachDeviceToDeviceStack によって 返されるポインターを格納します。 デバイスの次の下位ドライバーのデバイス オブジェクトを指すこのポインターは、デバイス スタックに IRP を渡すときに IoCallDriverPoCallDriver に必要なパラメーターです。

  9. FDO のDO_DEVICE_INITIALIZING フラグをクリアするか、次のようなステートメントを使用して DO をフィルター処理します。

    FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    
  10. デバイスの PnP IRP (IRP_MN_QUERY_RESOURCE_REQUIREMENTSIRP_MN_START_DEVICE) を処理するように準備する必要があります。

ドライバーは、PnP マネージャーによってデバイスに割り当てられているハードウェア リソースの一覧を含む IRP_MN_START_DEVICE を受け取るまで、デバイスの制御を開始しないでください。