If a driver needs to make it possible for applications to open the device object, it must create a symbolic link in the \Global?? directory to the device object’s name in the \Device directory. (See Chapter 3 in Part 1 for more information on \??.) Non–Plug and Play and file system drivers typically create a symbolic link with a well-known name (for example, \Device\Hardware2). Because well-known names don’t work well in an environment in which hardware appears and disappears dynamically, PnP drivers expose one or more interfaces by calling the IoRegisterDeviceInterface function, specifying a GUID (globally unique identifier) that represents the type of functionality exposed. GUIDs are 128-bit values that you can generate by using a tool called Uuidgen, which is included with the WDK and the Windows SDK. Given the range of values that 128 bits represents, it’s statistically almost certain that each GUID that Uuidgen creates will be forever and globally unique.
IoRegisterDeviceInterface generates the symbolic link associated with a device instance; however, a driver must call IoSetDeviceInterfaceState to enable the interface to the device before the I/O manager actually creates the link. Drivers usually do this when the PnP manager starts the device by sending the driver a start-device IRP—in this case, IRP_MJ_PNP, IRP_MN_START_DEVICE.
An application wanting to open a device object whose interfaces are represented with a GUID can call Plug and Play setup functions in user space, such as SetupDiEnumDeviceInterfaces, to enumerate the interfaces present for a particular GUID and to obtain the names of the symbolic links it can use to open the device objects. For each device reported by SetupDiEnumDeviceInterfaces, an application executes SetupDiGetDeviceInterfaceDetail to obtain additional information about the device, such as its autogenerated name. After obtaining a device’s name from SetupDiGetDeviceInterfaceDetail, the application can execute the Windows function CreateFile to open the device and obtain a handle.
EXPERIMENT: Looking at Device Objects
You can use the WinObj tool from Sysinternals or the !object kernel debugger command to view the device names under \Device in the object manager namespace. The following screen shot shows an I/O manager–assigned symbolic link that points to a device object in \Device with an autogenerated name:
When you run the !object kernel debugger command and specify the \Device directory, you should see output similar to the following:lkd> !object \Device
Object: 8b611b88 Type: (84d10d40) Directory
ObjectHeader: 8b611b70 (old version)
HandleCount: 0 PointerCount: 365
Directory Object: 8b602470 Name: Device
Hash Address Type Name
---- ------- ---- ----
00 85557a00 Device KsecDD
855589d8 Device Ndis
8b6151b0 SymbolicLink {941D252A-0BDA-4772-B3CB-30697579BD4A}
86859030 Device 0000009b
88c92da8 Device SrvNet
886723f0 Device Beep
8b71fb90 SymbolicLink ScsiPort2
84d17a98 Device 00000032
84d15f00 Device 00000025
84d13030 Device 00000019
01 86d44030 Device NDMP10
8d291eb0 SymbolicLink {E85EEE75-32E3-4A94-8905-52709C2C9BCC}
886da3c8 Device Netbios
86862030 Device 0000009c
84d177c8 Device 00000033
84d15c70 Device 00000026
02 86de9030 Device NDMP11
84d19320 Device 00000040
88633ca0 Device NetBT_Tcpip_{033C65A4-C1D6-4824-B420-DDAEADFF873E}
8b7dcdd0 SymbolicLink Ip
84d17500 Device 00000034
84d159a8 Device 00000027
03 86df3380 Device NDMP12
8515ede0 Device WMIAdminDevice
84d1a030 Device 00000041
8862e040 Device Video0
86eaec28 Device KeyboardClass0
84d03b00 Device KMDF0
84d17230 Device 00000035
84d156e0 Device 00000028
04 86e0d030 Device NDMP13
86e65030 Device NDMP20
85541030 Device VolMgrControl
86e6c358 Device Tun0
84d1ad68 Device 00000042
8862ec48 Device Video1
88e15158 Device 0000009f
9badd848 SymbolicLink MailslotRedirector
86e1d488 Device KeyboardClass1
...