Книга: Writing Windows WDM Device Drivers
Device Names
Device Names
The Wdm1 AddDevice code calls IoCreateDevice to create a Wdm1 device object. There are two ways to provide a name that is available to Win32 programs. The old way is to provide an explicit symbolic link name. The newfangled approach is to use a device interface to identify the devices that support a defined API.
Symbolic Links
The IoCreateDevice call has a DeviceName parameter that you can use to give your device a name. This name identifies the device to the kernel, not to Win32.
You must create a symbolic link to make the kernel device name available to Win32. To do this the old way, call IoCreateSymbolicLink at IRQL PASSIVE_LEVEL, passing the desired symbolic link name and the kernel device name as parameters.
Explicit device names created using this technique usually have a device number at the end. By convention, kernel device name numbers increment from zero, while symbolic link names increment from one.
The best way to illustrate device naming is using the WinObj tool, which only runs in NT and Windows 2000. WinObj is supplied in the Platform SDK, not the W2000 DDK. The standard serial ports have kernel device names deviceSerial0, deviceSerial1, etc. In WinObj, these names appear in the device folder.
Windows provides symbolic links "C0M1", "COM2", etc., to make these serial ports available to Win32. Symbolic links appear in the ?? folder in WinObj. You can double-click on each symbolic link to find out to which kernel device it refers. The screenshot in Figure 5.2 shows that COM3, ??com3, is a symbolic link to kernel device Serial0.
The ?? folder used to be called DosDevices, which you might come across in some old documentation.
Figure 5.2 WinObj tool screenshot
The Wdm1 driver could have given its first device object a kernel name of device Wdm1device0 and called IoCreateSymbolicLink to create a symbolic link with the name ??Wdm1dev1. A Win32 program would then have been able to open .Wdm1dev1 using CreateFile.
Note that C strings represent each character as "", so you would have to pass " \.Wdm1dev1" to CreateFile.
If this technique is used, you must keep track of how many devices are in use, so you can generate the correct names. If you use a global variable to keep the device count, you must use it carefully to ensure that simultaneous accesses do not corrupt its value. Achieve this using the InterlockedIncrement function that atomically increments a LONG value. This can be run at any IRQL and on paged memory. There are companion decrement, exchange, and compare functions.
Explicit kernel and symbolic link names are used most often in NT style drivers, which create devices in their DriverEntry routine. In this case, counting devices is easy, as you can be sure that no other part of your code will be trying to increment the device count.
You can use the QueryDosDevice Win32 function to get a list of all the symbolic link names currently available. For each symbolic link, you can call QueryDosDevice again to find the kernel name. QueryDosDevice is supposed to run in Windows 98, but I did not succeed in getting it to work. In NT and W2000, you can use the DefineDosDevice Win32 function to change symbolic links. You can experiment with both these commands using the dosdev utility in the W2000 DDK.
- A Tour of Linux Network Devices
- Constructing New Pathnames
- Chapter 5 Device Interfaces
- How Pathnames Represent Filenames
- namespace-uri()
- Creating and Deleting Device Objects
- Introduction to Serial Devices
- How Nameservers Store DNS Structure Information
- Configuring a Local Caching Nameserver
- Running the named Nameserver Daemon
- Devices
- The Disk as a Storage Device