Device ObjectEdit

Device Object is a kernel-mode data structure used by the I/O subsystem of Windows NT-based operating systems to represent a device to the operating system and to drivers. It is created by a driver to describe a physical or logical device and forms a stack with other device objects so that input/output operations flow through a chain of drivers. The device object is tightly tied to the I/O Manager I/O Manager and to per-device state stored in a per-device extension, which drivers use to maintain context across I/O requests. This model emphasizes modularity and reliability by isolating device-specific state and routing responsibilities through well-defined dispatch routines.

Device objects sit at the center of the device stack, a chain that starts with a top-level object and may pass IRPs down through lower-level drivers. Each object in the stack can process certain IRPs or pass them down to the next object via the standard interfaces provided by the I/O subsystem. The concept supports both physical devices and virtual or logical devices, enabling a wide range of hardware and software components to participate in a coherent I/O pipeline. The per-device extension stored in a device object is where a driver keeps device-specific state, buffers, and context needed to service requests. When a driver attaches to a device stack, it is responsible for implementing one or more dispatch routines (for example, handling create/open, read, write, or device control requests) and for coordinating with lower drivers in the stack IRPs and IoCallDriver calls.

Overview

  • A Device Object represents a single device in the system and is managed by a driver. It serves as a handle that the I/O Manager uses to route requests to the appropriate driver code.
  • The topmost object in a stack is created by the driver that owns the device interface; lower objects can be attached to the stack by other drivers to participate in the I/O path.
  • The per-device state is stored in the DeviceExtension, a memory region associated with the Device Object that drivers use to keep track of resources, state, and sometimes buffers.
  • The AttachedDevice pointer and the stack relationship define the path an IRP takes as it traverses from the originator of the request to the final target, enabling layered and modular driver architectures. See the concept of Device Stack and how a chain is formed.
  • Management of the object's lifecycle—creation, activation, and removal—interacts with functions such as IoCreateDevice and IoDeleteDevice and with attachment routines such as IoAttachDevice.

Structure and Lifecycle

  • Device Object basics: a kernel object with a place in the I/O path, carrying references to the owning DriverObject and a field for the DeviceExtension that holds per-device data.
  • Stack relationship: each Device Object can have a next-lower device in the chain (AttachedDevice), forming a stack that IRPs traverse.
  • Dispatch routines: drivers supply a set of routines that respond to standard IRPs (such as IRP_MJ_CREATE, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL) to implement device behavior. When a request cannot be fully handled by the top object, it can be forwarded to the next object in the chain via IoCallDriver.
  • Lifecycle steps: a driver creates a top-level Device Object with IoCreateDevice, optionally attaches to an existing stack with IoAttachDevice, and later tears down the chain with IoDeleteDevice when the device is removed or the driver unloads.

Creation, Attachment, and Detachment

  • IoCreateDevice: allocates and initializes a new top-level Device Object for a device exposed by a driver.
  • IoAttachDevice: attaches a newly created Device Object to a lower-level object, thereby forming a stack that handles IRPs in sequence.
  • Device removal: orderly detaching and deleting of Device Objects preserves system stability; drivers must complete any outstanding I/O, release resources, and call IoDeleteDevice to remove their presence from the stack.
  • Device extension allocation: the per-device state is typically allocated as part of or alongside Device Object initialization, and it may be accessed via the DeviceObject->DeviceExtension field.

Operation, IRPs, and Forwarding

  • IRPs (I/O Request Packets) flow through the device stack from the originator toward the target driver, with each device object in the chain having an opportunity to handle or modify the request.
  • Dispatch routines process specific IRP major functions; if a device can handle an IRP, it completes it; otherwise it may pass the IRP to the next lower driver using IoCallDriver.
  • Forwarding decisions and synchronization concerns are central to performance and robustness; well-designed stacks minimize contention and ensure that resources are released promptly to avoid leaks or deadlocks.

Device Extensions and State

  • The Device Extension is a driver-defined data structure associated with each Device Object; it stores per-device context like open handles, buffers, and hardware state.
  • Proper use of the Device Extension promotes isolation between devices and among drivers, helping to prevent cross-device interference and enabling safer module composition.
  • Extensions may also include pointers to hardware resources, DMA information, or queues for pending I/O, depending on the device class and driver design.

Security, Reliability, and Compatibility

  • The device object model supports reliability by isolating device-specific state within device extensions and by enforcing boundaries between drivers in a stack.
  • Security considerations include careful handling of IRPs, proper synchronization, bound checking, and constrained access to resources; driver signing and integrity checks are important for maintaining a trustworthy I/O path.
  • Compatibility across hardware generations and driver versions relies on stable interfaces and well-defined dispatch semantics, enabling incremental improvements without destabilizing the entire device stack.

See also