Initialisieren eines Geräteobjekts
Nachdem IoCreateDevice zurückgegeben wurde und der Aufrufer einen Zeiger auf ein DeviceObject gibt, das einen Zeiger auf die Geräteerweiterung enthält, müssen Treiber bestimmte Felder in den Geräteobjekten für ihre jeweiligen physischen, logischen und/oder virtuellen Geräte einrichten.
IoCreateDevice legt das StackSize-Feld eines neu erstellten Geräteobjekts auf eins fest. Ein Treiber der niedrigsten Ebene kann dieses Feld ignorieren. Wenn ein Treiber auf höherer Ebene IoAttachDeviceToDeviceStack aufruft , um sich selbst an den nächstniedrigen Treiber anzufügen, legt diese Routine das Feld StackSize im Geräteobjekt automatisch auf das feld des nächstniedrigen Treibers plus eins fest. Bei einigen Gerätetypen muss der Treiber auf höherer Ebene jedoch möglicherweise das Feld StackSize auf einen höheren Wert festlegen, wie in der gerätespezifischen Dokumentation beschrieben. Durch festlegen der Stapelgröße wird sichergestellt, dass IRPs, die an den Treiber auf höherer Ebene gesendet werden, einen treiberspezifischen E/A-Stapelspeicherort sowie die richtige Anzahl von E/A-Stapelspeicherorten für alle Treiber auf niedrigerer Ebene in der Kette enthalten.
IoCreateDevice legt das AlignmentRequirement-Feld eines neu erstellten Geräteobjekts auf die Datencachezeilengröße des Prozessors abzüglich 1 fest, um sicherzustellen, dass die in direkten E/A verwendeten Puffer ordnungsgemäß ausgerichtet werden. Nachdem IoCreateDevice zurückgegeben wurde, müssen Treiber physischer Geräte der niedrigsten Ebene die folgenden Aktionen ausführen:
Subtrahieren Sie eine von der Ausrichtungsanforderung des Geräts.
Vergleichen Sie das Ergebnis von Schritt 1 mit dem aktuellen Wert des AlignmentRequirement des Geräteobjekts.
Wenn die Ausrichtungsanforderung des Geräts größer ist, legen Sie AlignmentRequirement auf das Ergebnis von Schritt 1 fest. Behalten Sie andernfalls den Wert AlignmentRequirement wie von IoCreateDevice festgelegt bei.
Nachdem sich ein Treiber auf höherer Ebene durch Aufrufen von IoGetDeviceObjectPointer über einen anderen Treiber verkettet, muss der Treiber auf höherer Ebene das Feld AlignmentRequirement seines neu erstellten Geräteobjekts auf das des Geräteobjekts des nächstniedrigen Treibers festlegen. In der Regel sollte ein Treiber auf höherer Ebene diesen Wert nicht ändern. Wenn ein Treiber auf höherer Ebene IoAttachDevice oder IoAttachDeviceToDeviceStack aufruft, legen diese Routinen das Feld AlignmentRequirement im Geräteobjekt automatisch auf das feld des Treiberobjekts der niedrigeren Ebene fest.
IoGetDeviceObjectPointer gibt Zeiger sowohl auf das Geräteobjekt des Treibers der niedrigeren Ebene als auch auf das zugeordnete Dateiobjekt zurück. Nur ein FSD (oder möglicherweise ein anderer Treiber der höchsten Ebene) kann den zurückgegebenen Dateiobjektzeiger verwenden. Ein Zwischentreiber, der IoGetDeviceObjectPointer aufruft, sollte diesen Dateiobjektzeiger speichern, damit er durch Aufrufen von ObDereferenceObject dereferenziert werden kann, wenn der Treiber entladen wird.
Nachdem eine FSD das Volume eingebunden hat, das das Dateiobjekt enthält, das das Geräteobjekt eines niedrigeren Treibers darstellt, kann sich ein Zwischentreiber nicht zwischen dem Dateisystem und dem unteren Treiber verketten, indem IoAttachDevice oder IoAttachDeviceToDeviceStack aufgerufen wird. Darüber hinaus kann ein FSD den SectorSize-Member des Geräteobjekts basierend auf der Geometrie der zugrunde liegenden Volumehardware festlegen, wenn eine Einbindung erfolgt. Weitere Informationen finden Sie unter DEVICE_OBJECT.
Ein Treiber auf mittlerer oder niedrigster Ebene legt auch ein Bit in den Flags des Geräteobjekts fest, indem er es entweder mit DO_DIRECT_IO oder mit DO_BUFFERED_IO in jedem erstellten Geräteobjekt ausgibt. Treiber der obersten Ebene logischer oder virtueller Geräte können das Festlegen von Flags für gepufferte oder direkte E/A vermeiden, wenn der Treiberschreiber entscheidet, dass sich der zusätzliche Aufwand in einer besseren Treiberleistung auszahlt. Ein Zwischentreiber muss das Feld Flags seines Geräteobjekts so einrichten, dass es mit dem des Geräteobjekts des nächstniedrigen Treibers übereinstimmt.
Das Einrichten eines Geräteobjektfelds flags mit DO_DIRECT_IO oder DO_BUFFERED_IO bestimmt, wie der E/A-Manager den Zugriff auf Benutzerpuffer in allen anschließend an den Treiber gesendeten Datenübertragungsanforderungen übergibt.
Der Treiber kann dann alle anderen geräteabhängigen Werte im Geräteobjekt festlegen. Beispielsweise müssen Nicht-WDM-Treiber für Wechselmediengeräte oder das Flags-Element des Geräteobjekts mit DO_VERIFY_VOLUME, wenn sie während E/A-Vorgängen eine Medienänderung erkennen (oder vermuten). (Weitere Informationen finden Sie unter Unterstützen von Wechselmedien .) Treiber von Geräten, die Einschaltleistung erfordern, müssen ODER das Flags-Element mit DO_POWER_INRUSH, und Treiber von Geräten, die sich nicht im System paging-Pfad befinden, müssen ODER das Flags-Element mit DO_POWER_PAGABLE. Funktions- und Filtertreiber müssen das flag DO_DEVICE_INITIALIZING löschen.
Nach der Initialisierung des Geräteobjekts kann ein Treiber auch alle kerneldefinierte Objekte und andere systemdefinierte Datenstrukturen initialisieren, für die er Speicher in der Geräteerweiterung bereitgestellt hat. Wann genau ein Treiber diese Aufgaben ausführt, hängt von seinem Gerät, dem Typ des Objekts und/oder der Art der Daten ab. Im Allgemeinen können alle Objekte oder Datenstrukturen, die über PnP-Start- und Stoppanforderungen beibehalten werden können, in der AddDevice-Routine initialisiert werden. Diejenigen, die Ressourceninformationen erfordern, die mit einer PnP-IRP_MN_START_DEVICE-Anforderung bereitgestellt werden, oder die Änderungen erfordern, wenn das Gerät angehalten und/oder neu gestartet wird, sollten initialisiert werden, wenn der Treiber die IRP_MN_START_DEVICE-Anforderung verarbeitet. Weitere Informationen zu AddDevice-Routinen finden Sie unter Schreiben einer AddDevice-Routine.