Several times over the years we have seen this interesting situation where the system will bug check with 0x35 (NO_MORE_IRP_STACK_LOCATIONS) when our filter and other third party filters are installed on the same system. In some cases, this has rendered the system unbootable, for instance.
After researching this, we would find that a device object from our driver had too few stack locations listed. For example, the last time we debugged this, we had 3 stack locations (DeviceObject->StackSize was 3) and the driver to which we were attached had 9 stack locations.
We found this to be rather strange, since we do not adjust the size of our device object stack - we rely upon the I/O Manager to do this properly.
What that means is when we call IoAttachDeviceToDeviceStackSafe (or one of the related obsolete variants of this call) we count on the I/O Manager setting our StackSize field to be equal to the lower driver's StackSize field plus one. Thus, we were initially at a loss trying to figure out why we would have this invalid StackSize value.
It took us quite a bit of time to figure out what was happening, but what we found is that the filters in question would recycle their device objects after a mount. So, after our initial attachment we'd see something like:
Our Mount Detector -> Lower Filter Device -> File System
So our StackSize would be set to three. But later, using the same device object, we would find:
Our Filter -> Our Mount Detector -> Lower Filter Device -> File System -> Volume Manager -> (and on down the storage stack)
Our Filter Device had a StackSize value of 4, our Mount Detector Device had a StackSize value of 3, but the Lower Filter Device had a StackSize value of 9!
Further research into this revealed that this trick is one that SFILTER (in the IFS Kit) used to use (note: this is not the case in current versions!) Here is the comment from this older version of SFILTER:
// This is a mount request. Create a device object that can be
// attached to the file system's volume device object if this request
// is successful. Note that it is possible that there is a device
// object already on the FsDeviceQueue as the result of a mini-file
// system recognizer having recognized a volume. If so, then attempt
// to use it instead.
Thus, if another filter is attached to this device object, it will now be attached to the new device stack. However, IoAttachDeviceXxx functions adjusts only the StackSize field of the just-attached device object. Had it walked the entire stack, of course we would not have noticed this bug at all.
Another interesting bug that we've previously discussed relates to the FastIoDetachDevice call that must be supported by file system filter drivers. The sfilter implementation of this:
// Simply acquire the database lock for exclusive access, and detach from
// the file system's volume device object.
ExAcquireResourceExclusive( &FsLock, TRUE );
IoDetachDevice( TargetDevice );
IoDeleteDevice( SourceDevice );
ExReleaseResource( &FsLock );
The problem, of course, is that if the underlying file system processes the dismount in a dispatch entry point, this call deletes the device object before that IRP has been completed. Thus, the filter's completion routine is called and if the filter makes use of its device object (normally passed into its completion routine) the system will bug check.
Over the years, the file system filter team at Microsoft has found and resolved numerous problems in the SFILTER example. For anyone using SFILTER as the basis of their filter, we strongly recommend that you watch new versions, diffing older versions against newer versions to observe any bugs that have been fixed in the latest release. For those building other filter drivers, it is also useful to be aware of these changes because those older bugs might cause your filter driver to break!