Certain devices are exclusive access, or in simpler terms, only one handle can be opened for a particular device. A serial port is an example of an exclusive device; it would make no sense for 2 applications to have the port open because each would expect exclusive state with device plugged into the port and the settings (baud, parity, etc.) on the port itself.
You, as the driver writer, can also choose to make your device exclusive (if you are not writing a driver for a particular device class). Alternatively, you might choose to allow multiple handles to be created against your device. Finally, you might even want to have file system semantics for exclusive access or shared access (which is a whole topic in and of itself).
But what happens if you are trying to create a device which can have multiple handles created against it, but it ends up being exclusive for some unknown reason? How do yo debug this? The biggest aid in debugging this issue is understanding how you can create an exclusive device in the first place. Here is a list of ways of how to create an exclusive access device. (This list is by no means a exhaustive list, it just contains the methods I know of ;) ).
The DDK also has a great section on this topic, you can read it here. Hopefully the link does not move around.
As a further point of complexity, the I/O manager only enforces exclusivity on the base name of the device object. If the caller appends a string to the end of the base name, the I/O manager will not count that create as exclusive.
So, now that you know how to create an exclusive device object, how do you debug it? Well, you know if you are specifying Exclusive in IoCreateDevice(), so there is no need to debug that at runtime. What you can debug at runtime is a filter on top of you failing the create request. First, you run !devstack on your devobj to find the filter driver attached to your device. Then, run !drvobj [driver name] 3 and you will get the IRP_MJ_CREATE dispatch handler. Put a bp on that handler and then see if the request is being completed without being sent down the stack. Obviously you are now debugging code with out source, but at least you have a place to start.