デバイス オブジェクトの初期化
デバイス拡張機能へのポインターを含む DeviceObject へのポインターを呼び出し元に付与して、IoCreateDevice が値を返したら、ドライバーは、それぞれ物理、論理、または仮想デバイスのデバイス オブジェクトで特定のフィールドを設定する必要があります。
IoCreateDevice は、新しく作成されたデバイス オブジェクトの StackSize フィールドを 1 に設定します。 最下位レベルのドライバーは、このフィールドを無視できます。 上位レベルのドライバーが IoAttachDeviceToDeviceStack を呼び出して自身を次の下位ドライバーにアタッチすると、そのルーチンによって、デバイス オブジェクト内の StackSize フィールドが、次の下位ドライバーのデバイス オブジェクトの値 + 1 に自動的に設定されます。 ただし、デバイスの種類によっては、デバイス固有のドキュメントに記載されているように、上位レベルのドライバーで StackSize フィールドをより大きな値に設定する必要があります。 スタック サイズを設定すると、上位レベルのドライバーに送信される IRP には、ドライバー固有の I/O スタックの場所に加えて、チェーン内のすべての下位レベルのドライバーの正しい数の I/O スタックの場所が含められます。
IoCreateDevice は、直接 I/O で使用されるバッファーが正しく配置されるように、新たに作成されたデバイス オブジェクトの AlignmentRequirement フィールドをプロセッサのデータ キャッシュ ライン サイズから 1 を引いた値に設定します。 IoCreateDevice が値を返したら、最下位レベルの物理デバイス ドライバーで次の操作を行う必要があります。
デバイスのアラインメント要件から 1 減算します。
手順 1 の結果を、デバイス オブジェクトの AlignmentRequirement の現在の値と比較します。
デバイスのアライメント要件が大きい場合、AlignmentRequirement を手順 1 の結果に設定します。 それ以外の場合、IoCreateDevice によって設定された AlignmentRequirement 値のままにします。
上位レベルのドライバーが IoGetDeviceObjectPointer を呼び出すことによって自身を別のドライバーにチェーンした後、上位レベルのドライバーは、新しく作成されたデバイス オブジェクトの AlignmentRequirement フィールドを、次の下位レベルのドライバーのデバイス オブジェクトのフィールドに設定する必要があります。 原則として、上位レベルのドライバーはこの値を変更しないでください。 上位レベルのドライバーが IoAttachDevice または IoAttachDeviceToDeviceStack を呼び出した場合、これらのルーチンにより、デバイス オブジェクトの AlignmentRequirement フィールドが下位レベルのドライバーのデバイス オブジェクトのフィールドに自動的に設定されます。
IoGetDeviceObjectPointer は、下位レベルのドライバーのデバイス オブジェクトと、関連付けられているファイル オブジェクトの両方へのポインターを返します。 返されたファイル オブジェクト ポインターを使用できるのは、FSD (または、場合によっては別の最上位レベルのドライバー) だけです。 IoGetDeviceObjectPointer を呼び出す中間ドライバーは、ドライバーがアンロードされたときに ObDereferenceObject を呼び出すことによって逆参照できるよう、このファイル オブジェクト ポインターを保存する必要があります。
FSD が下位ドライバーのデバイス オブジェクトを表すファイル オブジェクトを含むボリュームをマウントすると、中間ドライバーは、IoAttachDevice または IoAttachDeviceToDeviceStack を呼び出すことにより、ファイル システムと下位ドライバーの間で自身を連結できません。 加えて、FSD は、マウントが 発生したときに、基になるボリューム ハードウェアのジオメトリに基づいて、デバイス オブジェクトの SectorSize メンバーを設定できます。 詳細については、DEVICE_OBJECT を参照してください。
さらに、中間または最下位レベルのドライバーは、作成されるすべてのデバイス オブジェクトで DO_DIRECT_IO または DO_BUFFERED_IO と共に OR を指定することにより、デバイス オブジェクトの Flags にビットも設定します。 必要な追加作業によってドライバーのパフォーマンス向上の効果があるとドライバー ライターが判断した場合、論理デバイスまたは仮想デバイスの最上位レベルのドライバーは、バッファーまたは直接 I/O の Flags の設定を回避することができます。 中間ドライバーは、次の下位ドライバーのデバイス オブジェクトと一致するよう、そのデバイス オブジェクトの Flags フィールドを設定する必要があります。
DO_DIRECT_IO または DO_BUFFERED_IO と共にデバイス オブジェクト Flags フィールドを設定すると、I/O マネージャーが、その後ドライバーに送信されるすべてのデータ転送要求でユーザー バッファーへのアクセスを渡す方法が決まります。
その後、ドライバーは、デバイス オブジェクト内の他のデバイスに依存する値を設定することができます。 たとえば、リムーバブル メディア デバイスの WDM 以外のドライバーは、I/O 操作中にメディアの変更を検出した (または疑われる) 場合、DO_VERIFY_VOLUME を持つデバイス オブジェクトの Flags メンバーに OR を停止する必要があります。 (「詳しくは、「リムーバブル メディアのサポート」を参照)。突入電力を必要とするデバイスのドライバーは、DO_POWER_INRUSH を持つ Flags メンバーに OR を指定する必要があり、システム ページング パス上にないデバイスのドライバーは DO_POWER_PAGABLE を持つ Flags メンバーに OR を指定する必要があります。 ファンクション ドライバーとフィルター ドライバーは、DO_DEVICE_INITIALIZING フラグをクリアする必要があります。
デバイス オブジェクトを初期化した後、ドライバーは、カーネル定義オブジェクトと、デバイス拡張機能にストレージを提供した他のシステム定義データ構造を初期化することもできます。 ドライバーがこれらのタスクを実行する正確なタイミングは、デバイス、オブジェクトの種類、データの性質によって異なります。 一般に、PnP の開始要求と停止要求を通じて永続化できるオブジェクトまたはデータ構造はすべて、AddDevice ルーチンで初期化できます。 PnP IRP_MN_START_DEVICE 要求で提供されるリソース情報が必要な場合、またはデバイスの停止時や再起動時に変更が必要な場合、ドライバーが IRP_MN_START_DEVICE 要求を処理するときに初期化する必要があります。 AddDevice ルーチンについて詳しくは、「AddDevice ルーチンの記述」をご覧ください。