16.8.2.1 Calling IoQueryDeviceDescription

NT device drivers can call IoQueryDeviceDescription to obtain the system-detected and system-supplied hardware configuration information about their devices from the registry.

Supplying a ConfigCallback Routine

A device driver that calls IoQueryDeviceDescription must provide a ConfigCallback routine, defined as follows:

NTSTATUS 
    (*PIO_QUERY_DEVICE_ROUTINE) ( 
        IN PVOID Context,                     //driver-determined 
        IN PUNICODE_STRING PathName, 
        IN INTERFACE_TYPE BusType,            //system-defined enum 
        IN ULONG BusNumber,                   //system-assigned count 
        IN PKEY_VALUE_FULL_INFORMATION *BusInformation, 
        IN CONFIGURATION_TYPE ControllerType, //system-defined enum 
        IN ULONG ControllerNumber, 
        IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, 
        IN CONFIGURATION_TYPE PeripheralType, //system-defined enum 
        IN ULONG PeripheralNumber, 
        IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation 
        ); 
 

The Context pointer passed to a ConfigCallback routine accesses a driver-determined storage area. However, the kernel-mode stack is limited in size: somewhat less than two pages are available for data storage by the DriverEntry and ConfigCallback routines and the amount of information returned cannot be predetermined. NT drivers usually call ExAllocatePool or ExAllocatePoolWithTag to allocate a paged pool buffer for the configuration information passed between their DriverEntry and ConfigCallback routines. The DriverEntry routine can free such a buffer when it has consumed and processed (as described in Section 16.8.3) the information supplied by its ConfigCallback routine.

Note the order of the bus, controller, and peripheral parameters to a ConfigCallback routine. The corresponding parameters to IoQueryDeviceDescription are declared to be optional, but the DriverEntry routine must supply appropriate values for at least one of the following sets of parameters when it calls IoQueryDeviceDescription:

Depending on the information requested when the DriverEntry routine calls IoQueryDeviceDescription, the PathName passed to the ConfigCallback routine points to a registry key that contains successively more device-specific and detailed information. For example, if a driver requests information only about a particular I/O bus in the machine, the PathName passed to the ConfigCallback routine would point to the key containing bus information. If the driver also requests information about both a ControllerType and a PeripheralType, the PathName parameter to the ConfigCallback routine would point to the registry key containing peripheral information.

Making Calls to IoQueryDeviceDescription

Figure 16.7 illustrates a device driver’s call to IoQueryDeviceDescription.

Figure 16.7 Getting Hardware Configuration Information from the Registry

Driver-supplied pointers for Context and the ConfigCallback routine are required parameters to IoQueryDeviceDescription. All other parameters are optional, so the caller can specify one or more of the bus, controller, and peripheral parameter sets, possibly in separate calls to IoQueryDeviceDescription with separate ConfigCallback routines. NT drivers usually need device-type-specific hardware information about a given ControllerType and/or PeripheralType.

System-defined enumerated values for the BusType parameter indicate the types of interfaces that I/O buses in Windows NT machines provide. The driver for a device that must be connected on an ISA bus would set BusType to the system-defined INTERFACE_TYPE value Isa when it called IoQueryDeviceDescription.

A device driver could also search for its devices on every I/O bus in the machine. Any driver can set BusType to successive values by using the system-defined value MaximumInterfaceType as a loop-control variable for calling IoQueryDeviceDescription, particularly if a driver constrains its query by specifying values for the ControllerType and/or PeripheralType parameters.

IoQueryDeviceDescription returns STATUS_OBJECT_NAME_NOT_FOUND if a particular type of bus is not available in the machine.

NT device drivers can use the following system-defined CONFIGURATION_TYPE values for the ControllerType and PeripheralType parameters to IoQueryDeviceDescription:

ControllerType Values:

PeripheralType Values:

DiskController

DiskPeripheral

TapeController

FloppyDiskPeripheral

CdromController

TapePeripheral

WormController

ModemPeripheral

SerialController

MonitorPeripheral

NetworkController

PrinterPeripheral

DisplayController

PointerPeripheral

ParallelController

KeyboardPeripheral

PointerController

TerminalPeripheral

KeyboardController

OtherPeripheral

AudioController

LinePeripheral

OtherController

NetworkPeripheral

Most of these defined type names are self-explanatory. However, the PeripheralType value MonitorPeripheral indicates a video monitor for which there is a corresponding video adapter. The value TerminalPeripheral indicates a so-called “dumb terminal” that displays data usually sent through a serial port. The value LinePeripheral indicates a peripheral device connected to the machine by a controller line.

Depending on which optional parameters the DriverEntry routine passes to IoQueryDeviceDescription, its ConfigCallback routine is given values for the corresponding parameters when it is called. A ConfigCallback routine can save these values (such as system-assigned bus numbers) in a temporary buffer, usually allocated from paged pool as described in Section 16.4.1.3 and released from the DriverEntry routine, or on the stack for subsequent calls to HAL routines.

IoQueryDeviceXxx Pointers Input to ConfigCallback

Depending on which optional parameters the DriverEntry routine passes to IoQueryDeviceDescription, a ConfigCallback routine is also given one or more nonNULL pointers to BusInformation, ControllerInformation, and PeripheralInformation, as shown in Figure 16.7. Each of these parameters is actually an array of pointers whose elements select ARC- or NtDetect-supplied information in the \Registry\Machine\Hardware\Description tree.

NT device drivers can use any of the following system-defined values to get to the kind(s) of bus, controller, or peripheral information they need from the registry:

As shown in Figure 16.7, NT device drivers usually get information from the registry of type CM_FULL_RESOURCE_DESCRIPTOR, for which they use the ControllerInformation[IoQueryDeviceConfigurationData] and/or PeripheralInformation[IoQueryDeviceConfigurationData] pointers.

Processing Configuration Information in ConfigCallback

As Figure 16.7 also shows, the IoQueryDeviceXxx pointers are valid only within the ConfigCallback routine. Moreover, NT drivers can read the value entries of subkeys under the key \Registry\Machine\Hardware\Description but cannot modify them. It is a ConfigCallback routine’s responsibility to copy pertinent system-supplied data it finds to a driver-allocated buffer (or driver-structured area on the stack) so the DriverEntry routine can use and, if necessary, supplement this information when the ConfigCallback routine returns control.

The CM_FULL_RESOURCE_DESCRIPTOR-type information shown in Figure 16.7 includes all controller- or peripheral-specific information that can be detected about one or more of the following:

Note that it is possible for a ConfigCallback routine to call HalTranslateBusAddress, HalGetInterruptVector, or HalGetAdapter, as long as it passes the values returned by these HAL routines to the DriverEntry routine. Note also that an NT device driver is required to call IoReportResourceUsage with the same values returned by IoGetDeviceDescription before it accesses the device, as explained in Section 16.8.3, so a ConfigCallback routine must not return control before it saves the information, if any, that it obtained from the registry for the DriverEntry routine.

The DeviceSpecificData, shown in Figure 16.7 at the tail of each partial resource descriptor in a partial resource list, is generally a device-type-specific structure. The system defines DeviceSpecificData structures for many kinds of peripheral devices. See ntddk.h for details.

On Return from ConfigCallback

Depending on the platform and/or type of bus, an NT driver might get only some of the machine-specific hardware information that it needs by calling IoQueryDeviceDescription. Depending on the device, some NT drivers also interrogate their devices to supplement system-supplied hardware configuration information.

While it supplies as much hardware configuration information as possible to each device driver, the system also requires each device driver to supply hardware configuration information about itself (and/or each of its devices) in the registry, as one of the following:

    NT device driver writers should consider the following an implementation guideline:

Every NT device driver must claim all the hardware resources in the machine that the driver and its device(s) need to carry out I/O operations before the driver actually initializes its device(s).

For more information about claiming these resources in the registry, see Section 16.8.3.