USB Audio 2.0 Class Driver for Windows
- Versa Deck Wdm Midi Device Driver Download
- Windows 10 Wdm Driver
- Wdm Sound Driver
- Versa Deck Wdm Midi Device Drivers
- VERSA DECK WDM MIDI Device Driver
- Yamaha USB-MIDI Driver Installation Guide 4 7 When the 'Welcome to the InstallShield Wizard for Yamaha USB-MIDI Driver' window appears, click Next. If the warning message below appears during the installation, click Install.
- NVIDIA WDM Drivers is a freeware software download filed under drivers and made available by Nvidia for Windows. The review for NVIDIA WDM Drivers has not been completed yet, but it was tested by an editor here on a PC.
- Windows MIDI drivers do not need to be implemented in the kernel, they can be implemented entirely in userspace as DLLs. MSDN has some information about the functions you need to implement - Audio Device Messages for MIDI - unfortunately it is somewhat lacking.
After reboot, make sure there is a SSL Soundscape WDM Device present in the category 'Sound, Video and Game Controllers' WDM integration - The 'easiest' option to tell Windows 7 something about system wide audio devices (WDM) is by right clicking on the speaker icon in the task bar (close to the clock) and selecting 'Properties'.
FeaturesSupported PlatformsDemoPrices
Thesycon's USB audio class driver TUSBAudio targets USB audio devices for professional and semi-professional use and highest quality audiophile HiFi systems. The driver supports devices which are compliant to the USB Audio 2.0 or USB Audio 1.0 device class specification. The driver provides an ASIO 2.3.1 compliant software interface and integrates with Windows as a standard WDM/DirectX compatible sound device. If the device provides MIDI features the driver exposes standard Windows MIDI ports.
To meet professional audio requirements, the audio class driver is optimized for low latency and low CPU load. Buffer depths can be adjusted by the user to optimize settings for a given computer. The driver implements a transparent (bit-perfect) playback and recording data path.
General
- supports Audio class 1.0 and Audio class 2.0 devices
- supports USB 2.0 full speed and high speed, and USB 3.0 super speed or higher
- supports standard sampling rates (depending on device capabilities):
44.1 kHz, 48 kHz, 88.2 kHz, 96 kHz, 176.4 kHz, 192 kHz, 352.8 kHz, 384 kHz, 705.6 kHz, 768 kHz, 1411.2 kHz, 1536 kHz - supports USB Audio Type I sample formats:
PCM 16 bit, PCM 24 bit, PCM 32 bit, FLOAT 32 bit - supports stereo and multi-channel configurations with as many channels as the device implements
ASIO
- ASIO 2.3.1 compliant driver DLL
- sample formats (depending on device capabilities): PCM 24 bit, PCM 32 bit
- bit-perfect playback and recording through ASIO
- playback mix (simultaneous ASIO and WDM playback)
- supports both 32-bit and 64-bit ASIO host applications
- multi-client support (multiple ASIO applications in parallel)
- configuration of ASIO buffer depth via driver control panel
- ASIO DSD mode supported (playback and recording), see below DSD Support
The TUSBAudio driver uses ASIO Driver Interface Technology and the Steinberg ASIO SDK. ASIO is a trademark and software of Steinberg Media Technologies GmbH.
WDM/DirectX Features
- standard Windows sound interfaces: MME, DirectSound, WASAPI
- stereo and multi-channel playback and recording sound devices (depending on device capabilities)
- flexible sound device configuration, for example:
8-channel unit can either be exposed as 7.1 or 4 x stereo playback - bit-perfect playback and recording through WASAPI
- volume and mute control through Windows standard GUI (depending on device capabilities)
- jack sensing (depending on device capabilities)
- PCM 16 bit, 24 bit, and 32 bit sample format (depending on device capabilities)
DSD Support
- native DSD mode through ASIO (see above)
- DSD over PCM (DoP) supported through ASIO and WDM
- DSD sample rates: DSD64 (2.8MHz), DSD128 (5.6MHz), DSD256 (11.3MHz), DSD512 (22.6MHz), DSD1024 (45.2MHz)
MIDI Features
- Windows compliant MIDI input and output ports (depending on device capabilities)
- Multiple applications can share a MIDI input port.
- Optionally, multiple applications can share a MIDI output port.
Virtual Channels Add-on
The Virtual Channels Add-on is an optional component of the TUSBAudio driver and has to be licensed additionally.
- virtual input or output channels can be defined (e.g. loopback channels)
- virtual WDM sound devices can be built from virtual channels
- arbitrary signal routing between physical and virtual channels can be configured
- routing and weights are fixed (not dynamically configurable through API)
Mixer Add-on
The Mixer Add-on is an optional component of the TUSBAudio driver and has to be licensed additionally.
- driver implements complete mixer matrix for all input and output channels
- any mixer weight can be controlled through API at runtime
- SDK included, contains sample application for mixer control
- virtual input or output channels can be defined (e.g. loopback channels)
- virtual WDM sound devices can be built from virtual channels
- application examples: monitor mix, loopback channels, channel swap, balance, etc.
- The driver will be delivered fully customized for licensee's product.
- Customization includes USB VID/PID, file names, text strings, etc.
- Windows 10 version of the driver is signed with Microsoft Attestation signing.
- Windows 7/8 version of the driver is signed with Thesycon's code signing certificate.
- Driver Customization Kit add-on: The Driver Customization Kit enables licensee to customize the driver by themselves.
- Wizard style user interface for interactive use
- Command line interface (silent mode) for integration into overall software setup
- Customization possible
- Control panel application with graphical user interface is included
- Device status and control via private programming interface (DLL)
- Source code of the control panel is part of the SDK.
- DFU utility with graphical user interface is included
- Firmware upgrade according to DFU device class
- Customization and Multi-language user interface is possible
- Source code of the DFU utility is part of the SDK.
NOTE: A DFU utility with identical functionality is available for macOS as well.
The SDK add-on is an optional component. It enables custom control panel development and direct access to custom firmware features. The SDK includes:
- API definition and link library for TUSBAudio API DLL
- API reference documentation
- Source Code of sample control panel implementation
- Source Code of DFU Application
Windows 8.1
Windows 8
Windows 7
The USB Audio 2.0 Class Driver for Windows implements the USB Audio 2.0 and 1.0 device class specification and is independent of the specific silicon and firmware solution used in a given device. As long as the hardware and firmware implement the descriptors, endpoints and requests defined in the class specification the driver should work. However, there are some requirements and assumptions as listed below.
- A device can implement a playback data path, a recording data path, or both.
- Both playback and recording path must be driven by the same sample clock source (as required by ASIO).
- An Audio 2.0 device must implement at least one clock source unit. If there is more than one clock source then a clock selector unit must be implemented as well.
- The driver supports the asynchronous, synchronous and adaptive endpoint synchronization model.
- If there is a recording path (IN endpoint) then the driver uses the incoming sample stream as clock reference to generate the outgoing stream (playback path).
- A playback-only device with an asynchronous OUT endpoint must implement a feedback endpoint.
- Optionally, a device can implement a feature unit to expose volume and mute controls.
Our software is purely designed and implemented by our team in Germany - no outsourcing. Technical support is provided directly by the developers.
Versa Deck Wdm Midi Device Driver Download
Current Version: 5.0
The USB controller is the only feature added to the model. ICH4 can be able to support USB 2.0, which allows for bandwidth speeds of 480, 40 times that which is possible with USB 1.1. Download inq1 nmea device (com8) driver. The ICH4 has an integrated control unit and an interface which allows it to be equipped with a local area network control chip, thus users do not have to install additional network cards. In some cases the ICH4 network controller can be able to transfer data at speeds of up to 1Gbits per second.
To receive a free demo, prices or license agreement, please fill out the contact form.
The free evaluation version of the TUSBAudio driver works for an interval of 60 days without any limitation. After that evaluation period has expired, the driver stops working.
NOTE: The driver described on this page is *not for use by end users*. It will not help solve any problems you may experience with a consumer device such as a webcam, camcorder, card reader, external sound card, etc. Thesycon's device drivers are software components intended to be used by hardware or software manufacturers to create end products.
For each USB device model an official USB vendor ID (VID) is required. Vendor IDs must be unique and will be assigned by the USB Implementers Forum (www.usb.org). Registration fees will be charged.
Thesycon owns a USB vendor ID and provides a subset of product IDs (PID) to licensees of Thesycon drivers.
Windows 10 Wdm Driver
© 2021 THESYCON
The Windows Driver Model formalizes a layering of drivers, as illustrated in Figure 2-1. A stack of device objects appears at the left of the figure. The device objects are data structures that the system creates to help software manage hardware. Many of these data structures can exist for a single piece of physical hardware. The lowest-level device object in a stack is called the physical device object, or PDO for short. Somewhere in the middle of a device object stack is an object called the functional device object, or FDO. Above and below the FDO there might be a collection of filter device objects. Filter device objects above the FDO are called upper filters, whereas filter device objects below the FDO (but still above the PDO) are called lower filters.
Figure 2-1.Layering of device objects and drivers in the WDM.
The Plug and Play (PnP) Manager component of the operating system constructs the stack of device objects at the behest of device drivers. For our purposes in this book, we can use the generic term bus to describe a piece of hardware to which devices connect electronically. This is a pretty broad definition. Not only does it include things like the PCI (Peripheral Component Interconnect) bus, but it also includes a SCSI (Small Computer System Interface) adapter, a parallel port, a serial port, a USB (universal serial bus) hub, and so on—anything, in fact, that can have multiple devices plugged into it. One responsibility of the driver for a bus is to enumerate the devices attached to the bus and to create PDOs for each of them. The PnP Manager begins painting the picture in Figure 2-1, then, by creating a PDO because some bus driver has detected some actual hardware.
Having created a PDO, the PnP Manager consults the registry database to find the filter and function drivers that occupy the middle of the figure. The setup program is responsible for many of these registry entries, and the INF files that control hardware installation are responsible for others. The registry entries define the order in which the drivers will appear in the stack, so the PnP Manager begins by loading the lowest-level filter driver and calling its AddDevice function. This function creates a FiDO, thus establishing the horizontal link between a FiDO and a driver. AddDevice then connects the PDO to the FiDO; that's where the line connecting the two device objects comes from. The PnP Manager proceeds upward, loading and calling each lower filter, the function driver, and each upper filter, until the stack is complete.
The purpose for the layering becomes apparent when you consider the flow of I/O requests diagrammed on the right-hand side of Figure 2-1. Each request for an operation affecting a device uses an I/O request packet (IRP). IRPs are normally sent to the topmost driver for the device and can percolate down the stack to the other drivers. At each level, the driver decides what to do with the IRP. Sometimes, a driver will do nothing except pass the IRP down. Other times, a driver might completely handle the IRP without passing it down. Still other times, a driver might process the IRP and pass it down, or vice versa. It all depends on the device and the exact semantics of the IRP. I'll explain in a later sidebar how it comes to pass that drivers can send IRPs down even though device objects are linked upward from the PDO.
The various drivers that occupy the stack for a single piece of hardware perform different roles. The function driver manages the device, represented by the FDO. The bus driver manages the connection between the device and the computer, represented by the PDO. Because of the close relationship between driver software and device object, I'll sometimes use the term FDO driver to mean the function driver and the term PDO driver to refer to the bus driver. The filter drivers, if they even exist, monitor or modify the stream of IRPs.
One of my seminar students, on seeing a diagram similar to Figure 2-1, was misled (I won't say by which teacher, who also wrote this book) into thinking of C++ and class inheritance. A perfectly reasonable way of designing an architecture for device drivers would be to define base classes from which programmers could derive progressively more specialized classes. In such a scheme, you could have a set of abstract classes that manage different sorts of PDOs, and you could derive FDO drivers from them. The system would send IRPs to virtual functions, some of which would be handled by the base class in the PDO driver and some of which would be handled by the derived class in the FDO driver. WDM doesn't work this way, though. The PDO driver performs completely different jobs from the FDO driver. The FDO driver 'delegates' certain work to the PDO driver by passing IRPs down to it, but the relationship is more like being peers in a bucket brigade (and we won't discuss the contents of the metaphorical buckets!) than like being hierarchically related.
How the System Loads Drivers
Having presented this much description of device layering in the WDM, it's time for me to be a bit more precise. To begin with, there's an obvious chicken-and-egg problem with what I've described. I said that the bus driver creates the PDO, but I also said that the PnP Manager loads drivers based on registry entries for a PDO that already exists. So where does the bus driver come from? I'll explain that in the next section. The registry database plays a crucial role in the process of loading drivers and configuring devices, so I'll explain which registry keys are relevant and what they contain.
Recursive Enumeration
In the first instance, the PnP Manager has a built-in 'driver' for a 'root' bus that doesn't actually exist. The root bus conceptually connects the computer to all hardware that can't electronically announce its presence—including the primary hardware bus (such as PCI). The root bus driver gets information about the computer from the registry, which was initialized by the Windows 2000 Setup program. Setup got the information by running an elaborate hardware detection program and by asking the end user suitable questions. Consequently, the root bus driver knows enough to create a PDO for the primary bus.
The function driver for the primary bus can then enumerate its own hardware electronically. The PCI bus, for example, provides a way of accessing a special configuration space for each attached device, and the configuration space contains a description of the device and its resource requirements. When a bus driver enumerates hardware, it acts in the guise of an ordinary function driver. Having detected a piece of hardware, however, the driver switches roles: it becomes a bus driver and creates a new PDO for the detected hardware. The PnP Manager then loads drivers for this device PDO, as previously discussed. It might happen that the function driver for the device enumerates still more hardware, in which case the whole process repeats recursively. The end result will be a tree like that shown in Figure 2-2, wherein a bus device stack branches into other device stacks for the hardware attached to that bus.
Figure 2-2.Layering of recursively enumerated devices.
The Role of the Registry
Three different registry keys bear on configuration. These are called the hardware key, the class key, and the service key. To be clear, these are not the proper names of specific subkeys: they are generic names of three keys whose pathnames depend on the device to which they belong. Broadly speaking, the hardware key contains information about a single device, the class key concerns all devices of the same type, and the service keys contains information about drivers. People sometimes use the name 'instance key' to refer to the hardware key and 'software key' to refer to the service key. The multiplicity of names derives from the fact that Windows 95/98 and Windows 2000 were written (mostly) by different people.
The Hardware (Instance) Keys Device hardware keys appear in the SystemCurrentControlSetEnum subkey of the local machine branch of the registry. You normally can't look inside this key because the system grants access to the System account only. In other words, kernel-mode programs and user-mode services running in the System account can read from and write to the Enum key and its subkeys, but not even an administrator can do so. To see what's inside Enum, you can run REGEDT32.EXE from an administrator-privilege account and change the security settings. Figure 2-3 illustrates the hardware key for one of the sample devices that accompanies this book (namely, the USB42 sample I'll discuss in Chapter 11, 'The Universal Serial Bus').
Figure 2-3.A hardware key in the registry.
The subkeys on the first level below the Enum key correspond to the different bus enumerators in the system. The description of all past or present USB devices is in the …EnumUSB subkey. I've expanded the key for the USB42 sample to show you how the device's hardware ID (vendor 0574, product 102A) has turned into the name of a key (Vid_0547&Pid_102A) and how a particular instance of the device that has that ID appears as a further subkey named 7&2. The 7&2 key is the hardware, or instance, key for this device.
Some of the values in the hardware key provide descriptive information that user-mode components such as the Device Manager can use. (You reach the Device Manager from the Management Console or, more easily, from the Hardware tab of the property sheet you get when you right-click the My Computer desktop icon and select Properties.) Figure 2-4 shows how the Device Manager portrays the properties of USB42. Refer to the sidebar 'Accessing Device Keys from User Mode' for an indication of how the Device Manager can gather this information even though it can't, by itself, get past the normal security block to the Enum key.
Figure 2-4.The Device Manager properties display for a device.
The hardware key also contains several values that identify the class of device to which the device belongs and the drivers for the device. ClassGUID is the ASCII representation of a globally unique identifier (GUID) that uniquely identifies a device class; in effect, it's a pointer to the class key for this device. Service is a pointer to the service key. Optional values (which USB42 doesn't have) named LowerFilters and UpperFilters, if present, would identify the service names for any lower or upper filter drivers, respectively.
Finally, a hardware key might have overriding values named Security, Exclusive, DeviceType, and DeviceCharacteristics that force the device object the driver will create to have certain attributes. I'll discuss the importance of these overrides later on when I tell you how to create a device object.
Most of the values in the hardware key get there automatically as part of the setup process or because the system recognizes new hardware (or gets told it about via the Hardware Wizard) sometime after initial setup. Some of the values get there because the INF file that's used to install the hardware directs that they be put there. I'll discuss INF files when I talk about how to plan for installation in Chapter 12, 'Installing Device Drivers.'
The Class Keys The class keys for all classes of device appear in the HKLMSystemCurrentControlSetControlClass key. Their key names are GUIDs assigned by Microsoft. Figure 2-5 illustrates the class key for SAMPLE devices, which is the class to which the USB42 sample and all the other sample drivers in this book belong.
Figure 2-5.A class key in the registry.
The USB class isn't particularly interesting as it lacks some of the optional values that might be there, such as these:
- LowerFilters and UpperFilters, if present, specify filter drivers for all devices of this class.
- Security, Exclusive, DeviceType, and DeviceCharacteristics, if present in a Properties subkey of the class key, specify values that override default settings of certain device object parameters for all devices of this class. These overrides have less precedence than the ones (if any) in the hardware key. System administrators will eventually be able to set up these overrides through the Management Console.
Each device also has its own subkey below the class key. The name of this key is the Driver value in the device's hardware key. Refer to Figure 2-6 for an illustration of the contents of this subkey, the purpose of which is to correlate all these registry entries with the INF file used to install the device.
Figure 2-6.A device-specific subkey of the device's class key in the registry.
The Service (Software) Keys The last key that's important for a device driver is the service key. It indicates where the driver's executable file is on disk and contains some other parameters that govern the way the driver is loaded. Service keys appear in the HKLMSystemCurrentControlSetServices key. Refer to Figure 2-7 for USB42's service key.
Figure 2-7.A service key in the registry.
It's not my purpose to rehash all the possible settings in the service key, which is splendidly documented in several places, including under the heading 'Service Install' in the Platform Software Development Kit (SDK). In this particular case, the values have the following significance:
- ImagePath indicates that the executable file for the driver is named USB42.SYS and can be found in %SystemRoot%system32drivers. Note that the registry setting in this case is a relative pathname starting from the system root directory.
- Type (1) indicates that this entry describes a kernel-mode driver.
- Start (3) indicates that the system should load this driver when it's needed to support a newly arrived device. (This numeric value corresponds to the SERVICE_DEMAND_START constant in a call to CreateService. When applied to a kernel-mode driver, it has the meaning I just described—it's not necessary to explicitly call StartService or issue a NET START command to start the driver.)
- ErrorControl (1) indicates that a failure to load this driver should cause the system to log the error and display a message box.
Order of Driver Loading
When the PnP Manager encounters a new device, it opens the hardware and class keys and proceeds to load drivers in the following order:
- Any lower filter drivers specified in the hardware key for the device. Since the LowerFilters value is of type REG_MULTI_SZ, it can specify more than one driver. They're loaded in the order in which they appear in the value's data string.
- Any lower filter drivers specified in the class key. Again, these are loaded in the order in which they appear in the LowerFilters value's data string.
- The driver specified by the Service value in the hardware key.
- Any upper filter drivers specified in the hardware key, in the order in which they appear in the UpperFilters data string.
- Any upper filter drivers specified in the class key, in the order in which they appear in the UpperFilters data string.
When I say the system 'loads' a driver, I mean that it maps the driver's image into virtual memory, fixes up relocatable references, and calls the driver's main entry point. The main entry point is usually named DriverEntry. I'll describe the DriverEntry function a bit further on in this chapter. It might turn out that a particular driver is already present in memory, in which case nothing happens at the load stage except incrementing a reference count that will preserve the image in memory for however long some device needs it.
You might have noticed that the loading of upper and lower filters belonging to the class and to the device instance isn't neatly nested as you might have expected. Before I knew the facts, I guessed that device-level filters would be closer to the function driver than class-level filters. As we'll see later on, it's not very important in what order the loading occurs. However, the system calls the drivers' AddDevice functions (another topic I'll discuss in considerable detail shortly) in the same order in which the PnP Manager loads the drivers. Consequently, the device object stack will mirror this order, with possibly unexpected results.
How Device Objects Interrelate
The tree of device object stacks shown in Figure 2-2 doesn't imply that IRPs necessarily flow from a PDO to the top FiDO for the next lower branch of the tree. In fact, the driver for one stack's PDO is the FDO driver for the next lower branch, as illustrated by the shading in the figure. When the driver receives an IRP in its PDO role, it will do something to perform the IRP, but that might not involve sending the same, or even any other, IRP to the devices in the stack it occupies while performing its FDO role. Conversely, when a bus driver receives an IRP in its FDO role, it might or might not need to send some IRPs to one or more of the devices for which it acts as PDO.
A few examples should clarify the relationship between FiDOs, FDOs, and PDOs. The first example concerns a read operation directed to a device that happens to be on a secondary PCI bus that itself attaches to the main bus through a PCI-to-PCI bridge chip. To keep things simple, let's suppose that there's one FiDO for this device, as illustrated in Figure 2-8. You'll learn in later chapters that a read request turns into an IRP with a major function code of IRP_MJ_READ. Such a request would flow first to the upper FiDO and then to the function driver for the device. (That driver is the one for the device object marked FDOdev in the figure.) The function driver calls the hardware abstraction layer (HAL) directly to perform its work, so none of the other drivers in the figure will see the IRP.
Figure 2-8.The flow of a read request for a device on a secondary bus.
A variation on the first example is shown in Figure 2-9. Here we have a read request for a device plugged into a USB hub that itself is plugged into the host controller. The complete device tree therefore contains stacks for the device, for the hub, and for the host controller. The IRP_MJ_READ flows through the FiDO to the function driver, which then sends one or more IRPs of a different kind downward to its own PDO. The PDO driver for a USB device is USBHUB.SYS, and it forwards the IRPs to the topmost driver in the host controller device stack, skipping the two-driver stack for the USB hub in the middle of the figure.
Figure 2-9.The flow of a read request for a USB device.
The third example is similar to the first, except that the IRP in question is a notification concerning whether a disk drive on a PCI bus will or will not be used as the repository for a system paging file. You'll learn in Chapter 6, 'Plug and Play,' that this notification takes the form of an IRP_MJ_PNP request with the minor function code IRP_MN_DEVICE_USAGE_NOTIFICATION. In this case, the FiDO driver will pass the request to the FDOdev driver, which will take note of it and pass it further down the stack to the PDOdev driver. This particular notification has implications about how other I/O requests that concern the PnP system or power management will be handled, so the PDOdev driver sends an identical notification to the stack within which it's the FDObus, as illustrated in Figure 2-10. (Not all bus drivers work this way, but the PCI bus does.)
Figure 2-10.The flow of a device usage notification.
Examining the Device Stack
To better visualize the way device objects and drivers are layered, it helps to have a tool. I wrote the DEVVIEW utility, which you'll find on the companion disc, for this purpose. I'll be describing other uses for DEVVIEW in this chapter, but the feature that concerns us now is its ability to display the device objects that are used to manage hardware devices. With the so-called Answer device plugged into my USB hub, I ran DEVVIEW and generated the two screen shots shown in Figure 2-11 and Figure 2-12.
This particular device uses only two device objects. The PDO is managed by USBHUB.SYS, whereas the FDO is managed by USB42.SYS (the image for the Answer device). In the first of these screen shots, you can see other information about the PDO. Based on our exploration of the registry keys associated with USB42, it should now be clear where that information came from.
It's worth experimenting with DEVVIEW on your own system to see how various drivers are layered for the hardware you own.
Figure 2-11.DEVVIEW information about USB42's PDO.
Figure 2-12.DEVVIEW information about USB42's FDO.
Driver Objects
The I/O Manager uses a driver object data structure to represent each device driver. See Figure 2-13. Like many of the data structures we'll be discussing, the driver object is partially opaque. This means that you and I are only supposed to directly access or change certain fields in the structure, even though the DDK headers declare the entire structure. I've shown the opaque fields of the driver object in the figure with a gray background. These opaque fields are analogous to the private and protected members of a C++ class, and the accessible fields are analogous to public members.
Figure 2-13.The DRIVER_OBJECT data structure.
The DDK headers declare the driver object, and all other kernel-mode data structures for that matter, in a stylized way, as this excerpt from WDM.H illustrates:
That is, the header declares a structure with a type name of DRIVER_OBJECT. It also declares a pointer type (PDRIVER_OBJECT) and assigns a structure tag (_DRIVER_OBJECT). This declaration pattern appears many places in the DDK, and I won't mention it again. The headers also declare a small set of type names (like CSHORT) to describe the atomic data types used in kernel mode. Table 2-1 lists some of these names. CSHORT, for example, means 'signed short integer used as a cardinal number.'
Table 2-1.Common type names for kernel-mode drivers.
Type Name | Description |
---|---|
PVOID, PVOID64 | Generic pointers (default precision and 64-bit precision) |
NTAPI | Used with service function declarations to force use of _ _stdcall calling convention on x86 architectures |
VOID | Equivalent to 'void' |
CHAR, PCHAR | 8-bit character, pointer to same (signed or not according to compiler default) |
UCHAR, PUCHAR | Unsigned 8-bit character, pointer to same |
SCHAR, PSCHAR | Signed 8-bit character, pointer to same |
SHORT, PSHORT | Signed 16-bit integer, pointer to same |
USHORT, PUSHORT | Unsigned 16-bit integer, pointer to same |
LONG, PLONG | Signed 32-bit integer, pointer to same |
ULONG, PULONG | Unsigned 32-bit integer, pointer to same |
WCHAR, PWSTR | Wide (Unicode) character or string |
PCWSTR | Pointer to constant Unicode string |
NTSTATUS | Status code (typed as signed long integer) |
LARGE_INTEGER | Signed 64-bit integer |
ULARGE_INTEGER | Unsigned 64-bit integer |
PSZ, PCSZ | Pointer to ASCIIZ (single-byte) string or constant string |
BOOLEAN, PBOOLEAN | TRUE or FALSE (equivalent to UCHAR) |
I'll briefly discuss the accessible fields of the driver object structure now.
DeviceObject (PDEVICE_OBJECT) anchors a list of device object data structures, one for each of the devices managed by the driver. The I/O Manager links the device objects together and maintains this field. The DriverUnload function of a non-WDM driver would use this field to traverse the list of device objects in order to delete them. A WDM driver probably doesn't have any particular need to use this field.
DriverExtension (PDRIVER_EXTENSION) points to a small substructure within which only the AddDevice (PDRIVER_ADD_DEVICE) member is accessible to the likes of us. (See Figure 2-14.) AddDevice is a pointer to a function within the driver that creates device objects; this function is rather a big deal, and I'll discuss it at length later in this chapter.
Figure 2-14.The DRIVER_EXTENSION data structure.
HardwareDatabase (PUNICODE_STRING) describes a string that names a hardware database registry key for the device. This is a name like 'RegistryMachineHardwareDescriptionSystem' and names the registry key within which resource allocation information resides. WDM drivers have no need to access the information below this key because the PnP Manager performs resource allocation automatically. The name is stored in Unicode. (In fact, all kernel-mode string data uses Unicode.) I'll discuss the format and the use of the UNICODE_STRING data structure in the next chapter.
The recorded videos can be saved on the hard drive or directly engraved on devices such as CD or DVD. Captures video from your computer screen, videotape recorder and other hardware easily and quickly.
FastIoDispatch (PFAST_IO_DISPATCH) points to a table of function pointers that file system and network drivers export. How these functions are used is beyond the scope of this book. If you're interested in learning more about file system drivers, consult Rajeev Nagar's Windows NT File System Internals: A Developer's Guide (O'Reilly & Associates, 1997).
DriverStartIo (PDRIVER_STARTIO) points to a function in your driver that processes I/O requests that the I/O Manager has serialized for you. I'll discuss request queuing in general and the use of this routine in particular in Chapter 5, 'The I/O RequestPacket.'
DriverUnload (PDRIVER_UNLOAD) points to a cleanup function in your driver. I'll discuss this function a bit further on in connection with DriverEntry, but you might as well know now that a WDM driver probably doesn't have any significant cleanup to do anyway.
MajorFunction (array of PDRIVER_DISPATCH) is a table of pointers to functions in your driver that handle each of the roughly two dozen types of I/O request. This table is also something of a big deal, as you might guess, because it defines how I/O requests make it into your code.
Device Objects
Figure 2-15 illustrates the format of a device object and uses the same shading convention for opaque fields that I used in the preceding discussion of driver objects. As the author of a WDM driver, you will create some of these objects by calling IoCreateDevice, but the I/O Manager will be responsible for managing them.
DriverObject (PDRIVER_OBJECT) points to the object describing the driver associated with this device object, usually the one that called IoCreateDevice to create it. Filter drivers sometimes need to use this pointer to find the driver object for a device they're filtering so that they can inspect entries in the MajorFunction table.
NextDevice (PDEVICE_OBJECT) points to the next device object that belongs to the same driver as this one. This field is the one that links device objects together starting from the driver object's DeviceObject member. There's probably no reason for a WDM driver to use this field.
Wdm Sound Driver
Figure 2-15.The DEVICE_OBJECT data structure.
CurrentIrp Acer acerpower fh (m460) driver download for windows. (PIRP) points to the I/O request packet most recently sent to the corresponding driver's StartIo function. I'll have more to say about the CurrentIrp field in Chapter 5 when I discuss cancel routines.
Flags (ULONG) contains a collection of flag bits. Table 2-2 lists the bits that are accessible to driver writers.
Table 2-2.Accessible flags in a DEVICE_OBJECT data structure.
Flag | Description |
---|---|
DO_BUFFERED_IO | Reads and writes use the buffered method (system copy buffer) for accessing user-mode data |
DO_EXCLUSIVE | Only one thread at a time allowed to open a handle |
DO_DIRECT_IO | Reads and writes use the direct method (memory descriptor list) for accessing user-mode data |
DO_DEVICE_INITIALIZING | Device object not initialized yet |
DO_POWER_PAGABLE | IRP_MJ_PNP must be handled at PASSIVE_LEVEL |
DO_POWER_INRUSH | Device requires large in-rush of current during power-on |
DO_POWER_NOOP | Device doesn't participate in power management |
Characteristics (ULONG) is another collection of flag bits describing various optional characteristics of the device. (See Table 2-3.) The I/O Manager initializes these flags based on an argument to IoCreateDevice. Filter drivers propagate them upward in the device stack.
Table 2-3.Characteristics flags in a DEVICE_OBJECT data structure.
Flag | Description |
---|---|
FILE_REMOVABLE_MEDIA | Media can be removed from device |
FILE_READ_ONLY_DEVICE | Media can only be read, not written |
FILE_FLOPPY_DISKETTE | Device is a floppy disk drive |
FILE_WRITE_ONCE_MEDIA | Media can be written once |
FILE_REMOTE_DEVICE | Device accessible through network connection |
FILE_DEVICE_IS_MOUNTED | Physical media is present in device |
FILE_DEVICE_SECURE_OPEN | Check security on device object during open operations |
Versa Deck Wdm Midi Device Drivers
DeviceExtension (PVOID) points to a data structure you define that will hold per-instance information about the device. The I/O Manager allocates space for the structure, but its name and contents are entirely up to you. A common convention is to declare a structure with the type name DEVICE_EXTENSION. To access it given a pointer (for example, fdo ) to the device object, use a statement like this one:
How the System Loads Drivers
Having presented this much description of device layering in the WDM, it's time for me to be a bit more precise. To begin with, there's an obvious chicken-and-egg problem with what I've described. I said that the bus driver creates the PDO, but I also said that the PnP Manager loads drivers based on registry entries for a PDO that already exists. So where does the bus driver come from? I'll explain that in the next section. The registry database plays a crucial role in the process of loading drivers and configuring devices, so I'll explain which registry keys are relevant and what they contain.
Recursive Enumeration
In the first instance, the PnP Manager has a built-in 'driver' for a 'root' bus that doesn't actually exist. The root bus conceptually connects the computer to all hardware that can't electronically announce its presence—including the primary hardware bus (such as PCI). The root bus driver gets information about the computer from the registry, which was initialized by the Windows 2000 Setup program. Setup got the information by running an elaborate hardware detection program and by asking the end user suitable questions. Consequently, the root bus driver knows enough to create a PDO for the primary bus.
The function driver for the primary bus can then enumerate its own hardware electronically. The PCI bus, for example, provides a way of accessing a special configuration space for each attached device, and the configuration space contains a description of the device and its resource requirements. When a bus driver enumerates hardware, it acts in the guise of an ordinary function driver. Having detected a piece of hardware, however, the driver switches roles: it becomes a bus driver and creates a new PDO for the detected hardware. The PnP Manager then loads drivers for this device PDO, as previously discussed. It might happen that the function driver for the device enumerates still more hardware, in which case the whole process repeats recursively. The end result will be a tree like that shown in Figure 2-2, wherein a bus device stack branches into other device stacks for the hardware attached to that bus.
Figure 2-2.Layering of recursively enumerated devices.
The Role of the Registry
Three different registry keys bear on configuration. These are called the hardware key, the class key, and the service key. To be clear, these are not the proper names of specific subkeys: they are generic names of three keys whose pathnames depend on the device to which they belong. Broadly speaking, the hardware key contains information about a single device, the class key concerns all devices of the same type, and the service keys contains information about drivers. People sometimes use the name 'instance key' to refer to the hardware key and 'software key' to refer to the service key. The multiplicity of names derives from the fact that Windows 95/98 and Windows 2000 were written (mostly) by different people.
The Hardware (Instance) Keys Device hardware keys appear in the SystemCurrentControlSetEnum subkey of the local machine branch of the registry. You normally can't look inside this key because the system grants access to the System account only. In other words, kernel-mode programs and user-mode services running in the System account can read from and write to the Enum key and its subkeys, but not even an administrator can do so. To see what's inside Enum, you can run REGEDT32.EXE from an administrator-privilege account and change the security settings. Figure 2-3 illustrates the hardware key for one of the sample devices that accompanies this book (namely, the USB42 sample I'll discuss in Chapter 11, 'The Universal Serial Bus').
Figure 2-3.A hardware key in the registry.
The subkeys on the first level below the Enum key correspond to the different bus enumerators in the system. The description of all past or present USB devices is in the …EnumUSB subkey. I've expanded the key for the USB42 sample to show you how the device's hardware ID (vendor 0574, product 102A) has turned into the name of a key (Vid_0547&Pid_102A) and how a particular instance of the device that has that ID appears as a further subkey named 7&2. The 7&2 key is the hardware, or instance, key for this device.
Some of the values in the hardware key provide descriptive information that user-mode components such as the Device Manager can use. (You reach the Device Manager from the Management Console or, more easily, from the Hardware tab of the property sheet you get when you right-click the My Computer desktop icon and select Properties.) Figure 2-4 shows how the Device Manager portrays the properties of USB42. Refer to the sidebar 'Accessing Device Keys from User Mode' for an indication of how the Device Manager can gather this information even though it can't, by itself, get past the normal security block to the Enum key.
Figure 2-4.The Device Manager properties display for a device.
The hardware key also contains several values that identify the class of device to which the device belongs and the drivers for the device. ClassGUID is the ASCII representation of a globally unique identifier (GUID) that uniquely identifies a device class; in effect, it's a pointer to the class key for this device. Service is a pointer to the service key. Optional values (which USB42 doesn't have) named LowerFilters and UpperFilters, if present, would identify the service names for any lower or upper filter drivers, respectively.
Finally, a hardware key might have overriding values named Security, Exclusive, DeviceType, and DeviceCharacteristics that force the device object the driver will create to have certain attributes. I'll discuss the importance of these overrides later on when I tell you how to create a device object.
Most of the values in the hardware key get there automatically as part of the setup process or because the system recognizes new hardware (or gets told it about via the Hardware Wizard) sometime after initial setup. Some of the values get there because the INF file that's used to install the hardware directs that they be put there. I'll discuss INF files when I talk about how to plan for installation in Chapter 12, 'Installing Device Drivers.'
The Class Keys The class keys for all classes of device appear in the HKLMSystemCurrentControlSetControlClass key. Their key names are GUIDs assigned by Microsoft. Figure 2-5 illustrates the class key for SAMPLE devices, which is the class to which the USB42 sample and all the other sample drivers in this book belong.
Figure 2-5.A class key in the registry.
The USB class isn't particularly interesting as it lacks some of the optional values that might be there, such as these:
- LowerFilters and UpperFilters, if present, specify filter drivers for all devices of this class.
- Security, Exclusive, DeviceType, and DeviceCharacteristics, if present in a Properties subkey of the class key, specify values that override default settings of certain device object parameters for all devices of this class. These overrides have less precedence than the ones (if any) in the hardware key. System administrators will eventually be able to set up these overrides through the Management Console.
Each device also has its own subkey below the class key. The name of this key is the Driver value in the device's hardware key. Refer to Figure 2-6 for an illustration of the contents of this subkey, the purpose of which is to correlate all these registry entries with the INF file used to install the device.
Figure 2-6.A device-specific subkey of the device's class key in the registry.
The Service (Software) Keys The last key that's important for a device driver is the service key. It indicates where the driver's executable file is on disk and contains some other parameters that govern the way the driver is loaded. Service keys appear in the HKLMSystemCurrentControlSetServices key. Refer to Figure 2-7 for USB42's service key.
Figure 2-7.A service key in the registry.
It's not my purpose to rehash all the possible settings in the service key, which is splendidly documented in several places, including under the heading 'Service Install' in the Platform Software Development Kit (SDK). In this particular case, the values have the following significance:
- ImagePath indicates that the executable file for the driver is named USB42.SYS and can be found in %SystemRoot%system32drivers. Note that the registry setting in this case is a relative pathname starting from the system root directory.
- Type (1) indicates that this entry describes a kernel-mode driver.
- Start (3) indicates that the system should load this driver when it's needed to support a newly arrived device. (This numeric value corresponds to the SERVICE_DEMAND_START constant in a call to CreateService. When applied to a kernel-mode driver, it has the meaning I just described—it's not necessary to explicitly call StartService or issue a NET START command to start the driver.)
- ErrorControl (1) indicates that a failure to load this driver should cause the system to log the error and display a message box.
Order of Driver Loading
When the PnP Manager encounters a new device, it opens the hardware and class keys and proceeds to load drivers in the following order:
- Any lower filter drivers specified in the hardware key for the device. Since the LowerFilters value is of type REG_MULTI_SZ, it can specify more than one driver. They're loaded in the order in which they appear in the value's data string.
- Any lower filter drivers specified in the class key. Again, these are loaded in the order in which they appear in the LowerFilters value's data string.
- The driver specified by the Service value in the hardware key.
- Any upper filter drivers specified in the hardware key, in the order in which they appear in the UpperFilters data string.
- Any upper filter drivers specified in the class key, in the order in which they appear in the UpperFilters data string.
When I say the system 'loads' a driver, I mean that it maps the driver's image into virtual memory, fixes up relocatable references, and calls the driver's main entry point. The main entry point is usually named DriverEntry. I'll describe the DriverEntry function a bit further on in this chapter. It might turn out that a particular driver is already present in memory, in which case nothing happens at the load stage except incrementing a reference count that will preserve the image in memory for however long some device needs it.
You might have noticed that the loading of upper and lower filters belonging to the class and to the device instance isn't neatly nested as you might have expected. Before I knew the facts, I guessed that device-level filters would be closer to the function driver than class-level filters. As we'll see later on, it's not very important in what order the loading occurs. However, the system calls the drivers' AddDevice functions (another topic I'll discuss in considerable detail shortly) in the same order in which the PnP Manager loads the drivers. Consequently, the device object stack will mirror this order, with possibly unexpected results.
How Device Objects Interrelate
The tree of device object stacks shown in Figure 2-2 doesn't imply that IRPs necessarily flow from a PDO to the top FiDO for the next lower branch of the tree. In fact, the driver for one stack's PDO is the FDO driver for the next lower branch, as illustrated by the shading in the figure. When the driver receives an IRP in its PDO role, it will do something to perform the IRP, but that might not involve sending the same, or even any other, IRP to the devices in the stack it occupies while performing its FDO role. Conversely, when a bus driver receives an IRP in its FDO role, it might or might not need to send some IRPs to one or more of the devices for which it acts as PDO.
A few examples should clarify the relationship between FiDOs, FDOs, and PDOs. The first example concerns a read operation directed to a device that happens to be on a secondary PCI bus that itself attaches to the main bus through a PCI-to-PCI bridge chip. To keep things simple, let's suppose that there's one FiDO for this device, as illustrated in Figure 2-8. You'll learn in later chapters that a read request turns into an IRP with a major function code of IRP_MJ_READ. Such a request would flow first to the upper FiDO and then to the function driver for the device. (That driver is the one for the device object marked FDOdev in the figure.) The function driver calls the hardware abstraction layer (HAL) directly to perform its work, so none of the other drivers in the figure will see the IRP.
Figure 2-8.The flow of a read request for a device on a secondary bus.
A variation on the first example is shown in Figure 2-9. Here we have a read request for a device plugged into a USB hub that itself is plugged into the host controller. The complete device tree therefore contains stacks for the device, for the hub, and for the host controller. The IRP_MJ_READ flows through the FiDO to the function driver, which then sends one or more IRPs of a different kind downward to its own PDO. The PDO driver for a USB device is USBHUB.SYS, and it forwards the IRPs to the topmost driver in the host controller device stack, skipping the two-driver stack for the USB hub in the middle of the figure.
Figure 2-9.The flow of a read request for a USB device.
The third example is similar to the first, except that the IRP in question is a notification concerning whether a disk drive on a PCI bus will or will not be used as the repository for a system paging file. You'll learn in Chapter 6, 'Plug and Play,' that this notification takes the form of an IRP_MJ_PNP request with the minor function code IRP_MN_DEVICE_USAGE_NOTIFICATION. In this case, the FiDO driver will pass the request to the FDOdev driver, which will take note of it and pass it further down the stack to the PDOdev driver. This particular notification has implications about how other I/O requests that concern the PnP system or power management will be handled, so the PDOdev driver sends an identical notification to the stack within which it's the FDObus, as illustrated in Figure 2-10. (Not all bus drivers work this way, but the PCI bus does.)
Figure 2-10.The flow of a device usage notification.
Examining the Device Stack
To better visualize the way device objects and drivers are layered, it helps to have a tool. I wrote the DEVVIEW utility, which you'll find on the companion disc, for this purpose. I'll be describing other uses for DEVVIEW in this chapter, but the feature that concerns us now is its ability to display the device objects that are used to manage hardware devices. With the so-called Answer device plugged into my USB hub, I ran DEVVIEW and generated the two screen shots shown in Figure 2-11 and Figure 2-12.
This particular device uses only two device objects. The PDO is managed by USBHUB.SYS, whereas the FDO is managed by USB42.SYS (the image for the Answer device). In the first of these screen shots, you can see other information about the PDO. Based on our exploration of the registry keys associated with USB42, it should now be clear where that information came from.
It's worth experimenting with DEVVIEW on your own system to see how various drivers are layered for the hardware you own.
Figure 2-11.DEVVIEW information about USB42's PDO.
Figure 2-12.DEVVIEW information about USB42's FDO.
Driver Objects
The I/O Manager uses a driver object data structure to represent each device driver. See Figure 2-13. Like many of the data structures we'll be discussing, the driver object is partially opaque. This means that you and I are only supposed to directly access or change certain fields in the structure, even though the DDK headers declare the entire structure. I've shown the opaque fields of the driver object in the figure with a gray background. These opaque fields are analogous to the private and protected members of a C++ class, and the accessible fields are analogous to public members.
Figure 2-13.The DRIVER_OBJECT data structure.
The DDK headers declare the driver object, and all other kernel-mode data structures for that matter, in a stylized way, as this excerpt from WDM.H illustrates:
That is, the header declares a structure with a type name of DRIVER_OBJECT. It also declares a pointer type (PDRIVER_OBJECT) and assigns a structure tag (_DRIVER_OBJECT). This declaration pattern appears many places in the DDK, and I won't mention it again. The headers also declare a small set of type names (like CSHORT) to describe the atomic data types used in kernel mode. Table 2-1 lists some of these names. CSHORT, for example, means 'signed short integer used as a cardinal number.'
Table 2-1.Common type names for kernel-mode drivers.
Type Name | Description |
---|---|
PVOID, PVOID64 | Generic pointers (default precision and 64-bit precision) |
NTAPI | Used with service function declarations to force use of _ _stdcall calling convention on x86 architectures |
VOID | Equivalent to 'void' |
CHAR, PCHAR | 8-bit character, pointer to same (signed or not according to compiler default) |
UCHAR, PUCHAR | Unsigned 8-bit character, pointer to same |
SCHAR, PSCHAR | Signed 8-bit character, pointer to same |
SHORT, PSHORT | Signed 16-bit integer, pointer to same |
USHORT, PUSHORT | Unsigned 16-bit integer, pointer to same |
LONG, PLONG | Signed 32-bit integer, pointer to same |
ULONG, PULONG | Unsigned 32-bit integer, pointer to same |
WCHAR, PWSTR | Wide (Unicode) character or string |
PCWSTR | Pointer to constant Unicode string |
NTSTATUS | Status code (typed as signed long integer) |
LARGE_INTEGER | Signed 64-bit integer |
ULARGE_INTEGER | Unsigned 64-bit integer |
PSZ, PCSZ | Pointer to ASCIIZ (single-byte) string or constant string |
BOOLEAN, PBOOLEAN | TRUE or FALSE (equivalent to UCHAR) |
I'll briefly discuss the accessible fields of the driver object structure now.
DeviceObject (PDEVICE_OBJECT) anchors a list of device object data structures, one for each of the devices managed by the driver. The I/O Manager links the device objects together and maintains this field. The DriverUnload function of a non-WDM driver would use this field to traverse the list of device objects in order to delete them. A WDM driver probably doesn't have any particular need to use this field.
DriverExtension (PDRIVER_EXTENSION) points to a small substructure within which only the AddDevice (PDRIVER_ADD_DEVICE) member is accessible to the likes of us. (See Figure 2-14.) AddDevice is a pointer to a function within the driver that creates device objects; this function is rather a big deal, and I'll discuss it at length later in this chapter.
Figure 2-14.The DRIVER_EXTENSION data structure.
HardwareDatabase (PUNICODE_STRING) describes a string that names a hardware database registry key for the device. This is a name like 'RegistryMachineHardwareDescriptionSystem' and names the registry key within which resource allocation information resides. WDM drivers have no need to access the information below this key because the PnP Manager performs resource allocation automatically. The name is stored in Unicode. (In fact, all kernel-mode string data uses Unicode.) I'll discuss the format and the use of the UNICODE_STRING data structure in the next chapter.
The recorded videos can be saved on the hard drive or directly engraved on devices such as CD or DVD. Captures video from your computer screen, videotape recorder and other hardware easily and quickly.
FastIoDispatch (PFAST_IO_DISPATCH) points to a table of function pointers that file system and network drivers export. How these functions are used is beyond the scope of this book. If you're interested in learning more about file system drivers, consult Rajeev Nagar's Windows NT File System Internals: A Developer's Guide (O'Reilly & Associates, 1997).
DriverStartIo (PDRIVER_STARTIO) points to a function in your driver that processes I/O requests that the I/O Manager has serialized for you. I'll discuss request queuing in general and the use of this routine in particular in Chapter 5, 'The I/O RequestPacket.'
DriverUnload (PDRIVER_UNLOAD) points to a cleanup function in your driver. I'll discuss this function a bit further on in connection with DriverEntry, but you might as well know now that a WDM driver probably doesn't have any significant cleanup to do anyway.
MajorFunction (array of PDRIVER_DISPATCH) is a table of pointers to functions in your driver that handle each of the roughly two dozen types of I/O request. This table is also something of a big deal, as you might guess, because it defines how I/O requests make it into your code.
Device Objects
Figure 2-15 illustrates the format of a device object and uses the same shading convention for opaque fields that I used in the preceding discussion of driver objects. As the author of a WDM driver, you will create some of these objects by calling IoCreateDevice, but the I/O Manager will be responsible for managing them.
DriverObject (PDRIVER_OBJECT) points to the object describing the driver associated with this device object, usually the one that called IoCreateDevice to create it. Filter drivers sometimes need to use this pointer to find the driver object for a device they're filtering so that they can inspect entries in the MajorFunction table.
NextDevice (PDEVICE_OBJECT) points to the next device object that belongs to the same driver as this one. This field is the one that links device objects together starting from the driver object's DeviceObject member. There's probably no reason for a WDM driver to use this field.
Wdm Sound Driver
Figure 2-15.The DEVICE_OBJECT data structure.
CurrentIrp Acer acerpower fh (m460) driver download for windows. (PIRP) points to the I/O request packet most recently sent to the corresponding driver's StartIo function. I'll have more to say about the CurrentIrp field in Chapter 5 when I discuss cancel routines.
Flags (ULONG) contains a collection of flag bits. Table 2-2 lists the bits that are accessible to driver writers.
Table 2-2.Accessible flags in a DEVICE_OBJECT data structure.
Flag | Description |
---|---|
DO_BUFFERED_IO | Reads and writes use the buffered method (system copy buffer) for accessing user-mode data |
DO_EXCLUSIVE | Only one thread at a time allowed to open a handle |
DO_DIRECT_IO | Reads and writes use the direct method (memory descriptor list) for accessing user-mode data |
DO_DEVICE_INITIALIZING | Device object not initialized yet |
DO_POWER_PAGABLE | IRP_MJ_PNP must be handled at PASSIVE_LEVEL |
DO_POWER_INRUSH | Device requires large in-rush of current during power-on |
DO_POWER_NOOP | Device doesn't participate in power management |
Characteristics (ULONG) is another collection of flag bits describing various optional characteristics of the device. (See Table 2-3.) The I/O Manager initializes these flags based on an argument to IoCreateDevice. Filter drivers propagate them upward in the device stack.
Table 2-3.Characteristics flags in a DEVICE_OBJECT data structure.
Flag | Description |
---|---|
FILE_REMOVABLE_MEDIA | Media can be removed from device |
FILE_READ_ONLY_DEVICE | Media can only be read, not written |
FILE_FLOPPY_DISKETTE | Device is a floppy disk drive |
FILE_WRITE_ONCE_MEDIA | Media can be written once |
FILE_REMOTE_DEVICE | Device accessible through network connection |
FILE_DEVICE_IS_MOUNTED | Physical media is present in device |
FILE_DEVICE_SECURE_OPEN | Check security on device object during open operations |
Versa Deck Wdm Midi Device Drivers
DeviceExtension (PVOID) points to a data structure you define that will hold per-instance information about the device. The I/O Manager allocates space for the structure, but its name and contents are entirely up to you. A common convention is to declare a structure with the type name DEVICE_EXTENSION. To access it given a pointer (for example, fdo ) to the device object, use a statement like this one:
It happens to be true (now, anyway) that the device extension immediately follows the device object in memory. It would be a bad idea to rely on this always being true, though, especially when the documented method of following the DeviceExtension pointer will always work.
DeviceType (DEVICE_TYPE) is an enumeration constant describing what type of device this is. The I/O Manager initializes this member based on an argument to IoCreateDevice. Filter drivers might conceivably need to inspect it. At the date of this writing, there are roughly 50 possible values for this member. (See Table 2-4.)
Table 2-4.Device type codes and default security.
Device Type | Default Security |
---|---|
FILE_DEVICE_BEEP | Public Open Unrestricted |
FILE_DEVICE_CD_ROM | Modified Public Default Unrestricted |
FILE_DEVICE_CD_ROM_FILE_SYSTEM | Public Default Unrestricted |
FILE_DEVICE_CONTROLLER | Public Open Unrestricted |
FILE_DEVICE_DATALINK | Public Open Unrestricted |
FILE_DEVICE_DFS | Public Open Unrestricted |
FILE_DEVICE_DISK | Modified Public Default Unrestricted |
FILE_DEVICE_DISK_FILE_SYSTEM | Public Default Unrestricted |
FILE_DEVICE_FILE_SYSTEM | Public Default Unrestricted |
FILE_DEVICE_INPORT_PORT | Public Open Unrestricted |
FILE_DEVICE_KEYBOARD | Public Open Unrestricted |
FILE_DEVICE_MAILSLOT | Public Open Unrestricted |
FILE_DEVICE_MIDI_IN | Public Open Unrestricted |
FILE_DEVICE_MIDI_OUT | Public Open Unrestricted |
FILE_DEVICE_MOUSE | Public Open Unrestricted |
FILE_DEVICE_MULTI_UNC_PROVIDER | Public Open Unrestricted |
FILE_DEVICE_NAMED_PIPE | Public Open Unrestricted |
FILE_DEVICE_NETWORK | Modified Public Default Unrestricted |
FILE_DEVICE_NETWORK_BROWSER | Public Open Unrestricted |
FILE_DEVICE_NETWORK_FILE_SYSTEM | Modified Public Default Unrestricted |
FILE_DEVICE_NULL | Public Open Unrestricted |
FILE_DEVICE_PARALLEL_PORT | Public Open Unrestricted |
FILE_DEVICE_PHYSICAL_NETCARD | Public Open Unrestricted |
FILE_DEVICE_PRINTER | Public Open Unrestricted |
FILE_DEVICE_SCANNER | Public Open Unrestricted |
FILE_DEVICE_SERIAL_MOUSE_PORT | Public Open Unrestricted |
FILE_DEVICE_SERIAL_PORT | Public Open Unrestricted |
FILE_DEVICE_SCREEN | Public Open Unrestricted |
FILE_DEVICE_SOUND | Public Open Unrestricted |
FILE_DEVICE_STREAMS | Public Open Unrestricted |
FILE_DEVICE_TAPE | Public Open Unrestricted |
FILE_DEVICE_TAPE_FILE_SYSTEM | Public Default Unrestricted |
FILE_DEVICE_TRANSPORT | Public Open Unrestricted |
FILE_DEVICE_UNKNOWN | Public Open Unrestricted |
FILE_DEVICE_VIDEO | Public Open Unrestricted |
FILE_DEVICE_VIRTUAL_DISK | Modified Public Default Unrestricted |
FILE_DEVICE_WAVE_IN | Public Open Unrestricted |
FILE_DEVICE_WAVE_OUT | Public Open Unrestricted |
FILE_DEVICE_8042_PORT | Public Open Unrestricted |
FILE_DEVICE_NETWORK_REDIRECTOR | Public Open Unrestricted |
FILE_DEVICE_BATTERY | Public Open Unrestricted |
FILE_DEVICE_BUS_EXTENDER | Public Open Unrestricted |
FILE_DEVICE_MODEM | Public Open Unrestricted |
FILE_DEVICE_VDM | Public Open Unrestricted |
FILE_DEVICE_MASS_STORAGE | Modified Public Default Unrestricted |
FILE_DEVICE_SMB | Public Open Unrestricted |
FILE_DEVICE_KS | Public Open Unrestricted |
FILE_DEVICE_CHANGER | Public Open Unrestricted |
FILE_DEVICE_SMARTCARD | Public Open Unrestricted |
FILE_DEVICE_ACPI | Public Open Unrestricted |
FILE_DEVICE_DVD | Public Open Unrestricted |
FILE_DEVICE_FULLSCREEN_VIDEO | Public Open Unrestricted |
FILE_DEVICE_DFS_FILE_SYSTEM | Public Open Unrestricted |
FILE_DEVICE_DFS_VOLUME | Public Open Unrestricted |
FILE_DEVICE_SERENUM | Public Open Unrestricted |
FILE_DEVICE_TERMSRV | Public Open Unrestricted |
FILE_DEVICE_KSEC | Public Open Unrestricted |
StackSize (CCHAR) counts the number of device objects starting from this one and descending all the way to the PDO. The purpose of this field is to inform interested parties about how many stack locations should be created for an IRP that will be sent first to this device's driver. WDM drivers don't normally need to modify this value, however, because the support routines they use for building the device stack do so automatically.