Every physical device object (PDO) must have a name. Furthermore, if you read the entire MSDN page, you see that any device attached to the PDO must not have a name. Why does such a rule exist? To answer this question, let’s explore what happens if more than one device in the stack has a name. Furthermore, each named device has a symbolic link created against it so that a user mode application can easily create a file handle, as shown by this diagram
| FDO |
| \Device\Name2 | <– Symbolic link \DosDevices\Name2
| PDO |
| \Device\Name1 | <– Symbolic link created by IoRegisterDeviceInterface
To process the CreateFile request, the I/O manager resolves the symbolic name to the underlying device name and sends the IRP_MJ_CREATE to the top of the stack. If the create succeeds, all I/O flows through the top of the stack and it is up to the stack to forward or process I/O requests as appropriate. This means that no matter which name (\DosDevices\Name2 or the device interface name returned by SetupAPI) you used to open the device stack, the I/O will always be sent to the top. It is not as if you can open the stack by the PDO’s name and send I/O to the PDO directly without the FDO seeing the I/O requests. So, why are having additional names a problem in this scenario? The answer is that this is not the reason that this rule exists.
So, again, why does this rule exist? The rule exists because of how the I/O manager uses the device object derived from the device name/symbolic when creating a file handle. Each device has its own set of properties (exclusive, secure open, security descriptor) that are specified when the device is created by calling IoCreateDevice or IoCreateDeviceSecure and uses the properties associated with only this device object and not any other device object in the stack. This means that if the PDO has a security descriptor that allows access only to user A and excludes B, while the FDO has a security descriptor that allows access only to user B, user B can open the stack by using the FDO’s name and circumvent the PDO’s security settings. In other words, you have a potential security hole! Since each name is evaluated on its own, every named device in the stack can be opened with their own set of rights and properties.
This leads to 2 more questions.
How do I specify the properties (exclusivity, security, etc) I want for the stack if I can’t have a name and some other driver is creating the PDO?
This is a legitimate problem. If your driver has no control over how the PDO is created, how can you affect its settings? Or to turn it around, how is the bus driver going to know what settings are appropriate for the PDO it is creating? Most bus drivers do not know what specific driver will be loaded on the PDO it is enumerating. To fix this, the PnP manager will adjust the settings of each device object in the stack to a specific value. These values are written to the device node during installation by the INF. You use the hardware AddReg directive to tell the PnP manager what to set for the stack. Using the INF, you can set stack wide settings for device characteristics, device type, security, and exclusivity.
Why do some stacks have named device objects in their stacks that are not the PDO?
Some stacks have named FDOs or filters because of legacy reasons that predate PnP. For instance, the storage stacks name their device objects because other system components expect to find these names. In these stacks which have multiple device objects with a name, you can still use the INF directives to create stack wide settings.