J.
I would recommend that your filter call MmGetSystemRoutineAddress to see
if FsRtlRegisterFileSystemFilterCallbacks is defined. If it is, do it
the way the filespy sample shows you. On W2K when this API is present
(which is coming) it will work as well as always on XP and later.
In the case that this API does not exist the only available method for
receiving these callbacks is for you to hook the file systems directly.
Below is an email sent out by RaviSp from Microsoft a couple of years
ago which describes the best way of doing this on W2K. If you decide
you need to do this I highly recommend you do it exactly as described
below.
Neal Christiansen
Microsoft File System Filter Group Lead
This posting is provided “AS IS” with no warranties, and confers no
rights
Since many people have been expressing interest on how to hook the fast
i/o callbacks into the filesystem in Win 2K & below, here’s an example
below of a reasonably safe way of doing it, while being a good citizen
with respect to other filters in the system who might wish to do the
same.
For Windows XP, filters should use
FsRtlRegisterFilesystemFilterCallbacks() to receive callbacks for the
below routines automatically. (Do NOT use the below method on XP. You
may have to #ifdef code appropriately and I can understand it’s yucky,
but this is STRICTLY for Win 2K & below ONLY)
AcquireFileForNtCreateSection
ReleaseFileForNtCreateSection
AcquireForModWrite
ReleaseForModWrite
AcquireForCcFlush
ReleaseForCcFlush
For Windows 2000 & below, there was no way to register for these. Cc &
Mm directly called in to the base filesystem. If filters really, really
want to hook them in these OS versions, here are the guidelines:
-
First of all these guidelines & the technique presented below is ONLY
targeted towards local filesystems. There are complications when you are
filtering remote filesystems that I will have to address separately in
another email if there’s interest.
-
Hook them in the FsNotification() callback for file system
registration notification
-
Hook the Release*() callback before the corresponding Acquire*()
callback. This eliminates the window where their acquire can be called
without a corresponding release.
-
When mangling the file system’s dispatch table you need to remember &
directly replace the appropriate FastIo dispatch in the base
filesystem’s driver object. NOT the immediate lower device object. This
will ensure if there are multiple filters who hook it, it’ll chain
right.
-
When their dispatch is called, they need to do their work & then call
the routine that they replaced in step 3.)
-
This is more of a note: in Windows 2K & below you cannot fail the
AcquireFileForNtCreateSection callback regardless - XP allows u to fail
it.
Here’s an example of the right way to hook it. This will hook it in the
FsNotification() routine that is called when a filesystem registers
itself. The below example shows how to hook the
AcquireFileForNtCreateSection/ReleaseFileForNtCreateSection callbacks.
The others can be similarly hooked.
Once hooked, the old routines are remembered in OldAcquire* , and
OldRelease* function pointers.
When the filter’s Acquire*(), Release*() are called, they should simply
do their work and then proceed to call the OldAcquireFile*() and
OldRelease*() functions appropriately.
VOID
MyFsNotification(
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN FsActive
)
{
…
if (FsActive) {
PDEVICE_EXTENSION deviceExtension;
//
// The file system has registered as an active file system. If it
is
// a disk-based file system attach to it.
//
…
status = IoCreateDevice(
MyFsDriverObject,
sizeof( DEVICE_EXTENSION ),
(PUNICODE_STRING) NULL,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&myDeviceObject
);
if (NT_SUCCESS( status )) {
deviceExtension = myDeviceObject->DeviceExtension;
fsDevice = deviceExtension->FileSystemDeviceObject =
IoAttachDeviceToDeviceStack(myDeviceObject,
DeviceObject);
…
} else {
//
// Error
//
…
return;
}
//
// Hook Release first: to hook we have to remember the old
dispatch and set the new one atomically.
// This is achieved by using an interlocked compare exchange.
//
ASSERT ((DeviceObject->DriverObject->FastIoDispatch != NULL) &&
(DeviceObject->DriverObject->FastIoDispatch->SizeOfFastIoDispatch >
FIELD_OFFSET(FAST_IO_DISPATCH,
ReleaseFileForNtCreateSection)) &&
(DeviceObject->DriverObject->FastIoDispatch->ReleaseFileForNtCreateSecti
on != NULL));
do {
//
// Save the old dispatch
//
deviceExtension-> OldReleaseForNtCreateSection =
DeviceObject->DriverObject->FastIoDispatch->ReleaseFileForNtCreateSectio
n;
} while ( InterlockedCompareExchangePointer(
&(DeviceObject->DriverObject->FastIoDispatch->ReleaseFileForNtCreateSect
ion),
MyFastIoReleaseFileForNtCreateSection,
deviceExtension->OldReleaseForNtCreateSection) !=
deviceExtension-> OldReleaseForNtCreateSection );
//
// Hook in our FastIoDispatch for FsRtlAcquireFileExclusive
callback
//
ASSERT ((DeviceObject->DriverObject->FastIoDispatch != NULL) &&
(DeviceObject->DriverObject->FastIoDispatch->SizeOfFastIoDispatch >
FIELD_OFFSET(FAST_IO_DISPATCH,
AcquireFileForNtCreateSection)) &&
(DeviceObject->DriverObject->FastIoDispatch->AcquireFileForNtCreateSecti
on != NULL));
do {
//
// Save the old dispatch
//
deviceExtension->OldAcquireForNtCreateSection =
DeviceObject->DriverObject->FastIoDispatch->AcquireFileForNtCreateSectio
n;
} while ( InterlockedCompareExchangePointer(
&(DeviceObject->DriverObject->FastIoDispatch->AcquireFileForNtCreateSect
ion),
MyFastIoAcquireFileForNtCreateSection,
deviceExtension->OldAcquireForNtCreateSection ) !=
deviceExtension->OldAcquireForNtCreateSection );
…
}
…
}
Here’s an example of how to locate your device object in the hooked
routine & also how to pass the call down to the filter below you.
Note that this method of locating your device object is only needed for
the AcquireForNtCreateSection/ReleaseForNtCreateSection callbacks.
The rest of the callbacks have the device object passed in, which can be
directly used.
VOID
MyFastIoAcquireFileForNtCreateSection(
IN PFILE_OBJECT FileObject
)
{
PDEVICE_OBJECT deviceObject, fsDeviceObject;
BOOLEAN found = FALSE;
fsDeviceObject = IoGetBaseFileSystemDeviceObject( FileObject );
for (deviceObject = fsDeviceObject->AttachedDevice; deviceObject
!= NULL ; deviceObject = deviceObject->AttachedDevice) {
//
// Assume that driver object for this filter is stored
in a global MyDriverObject
//
if (deviceObject->DriverObject == MyDriverObject) {
//
// Located our device object
//
found = TRUE;
break;
}
}
//
// Since this filter only filters local filesystems we should
ALWAYS be able to locate our device object
// on the stack. Hence the assert below. For remote filesystems it
is possible that the base fs device
// object is owned by MUP instead of the RDR that we actually
attached to, hence this assert can fire
// if this filter attempted to ever filter a remote file system.
Which this filter is not designed to…
ASSERT( found == TRUE );
ASSERT( deviceObject->DeviceExtension != NULL );
//
// deviceObject now points to our device.
// Do any relevant pre-processing
//
…
return deviceObject->DeviceExtension->
OldAcquireForNtCreateSection( FileObject ); }
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of J. McConnell
Sent: Saturday, September 25, 2004 11:53 PM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] XP callbacks equivalent in Win2K for FS filter
I’m writing a file system filter driver based on the filespy example in
the
XP DDK. Attempting to test my code in win2k I came across the problem
that
filespy now uses FsRtlRegisterFileSystemFilterCallbacks, which is
unavailable in win2k and I need something that will work in both XP and
2K.
What is the best method of accomplishing this?
Links or suggested offline resources would be great.
Thanks,
–
J. McConnell
http://www.j-dotonline.com
Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17
You are currently subscribed to ntfsd as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com