Sfilter是MS提供的一个例子文件系统过滤驱动程序。在IFS Kit中可以找到源代码。在系统安全等相关方面等用得很多了,例如 文件的透明加密解密,只允许特定的进程访问特定的文件。Sfilter可以在XP,20003中动态加载,在2000下确不可以。通过如下的代码可以实现在2000下的动态加载。
有两种方法可以实现。第一种是首先获得文件系统驱动DRIVER_OBJECT的指针,然后通过,然后通过遍历DRIVER_OBJECT中保存的设备对象的链表,得到已经被文件系统驱动MOUNT的卷设备对象指针。代码如下
//声明未公开的变量的函数原型
extern POBJECT_TYPE *IoDriverObjectType;
extern
NTKERNELAPI
NTSTATUS
ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID *Object );
VOID
SfAttachToVolumeDevice( )
{
UNICODE_STRING szLinkPath;
PDRIVER_OBJECT lpDriverObject;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
PDEVICE_OBJECT currentDevice = NULL;
RtlInitUnicodeString(&szLinkPath, L"//FileSystem//FastFat");
InitializeObjectAttributes(&ObjectAttributes,
&szLinkPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ObReferenceObjectByName( &szLinkPath,
OBJ_CASE_INSENSITIVE,
NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
&lpDriverObject );
currentDevice = lpDriverObject->DeviceObject;
while( currentDevice != NULL )
{
SfFsNotification( currentDevice, TRUE );
currentDevice = currentDevice->NextDevice;
}
RtlInitUnicodeString(&szLinkPath, L"//FileSystem//Ntfs");
InitializeObjectAttributes(&ObjectAttributes,
&szLinkPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = ObReferenceObjectByName( &szLinkPath,
OBJ_CASE_INSENSITIVE,
NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
&lpDriverObject);
currentDevice = lpDriverObject->DeviceObject;
while( currentDevice != NULL ){
SfFsNotification( currentDevice, TRUE );
currentDevice = currentDevice->NextDevice;
}
}
}
}
第二种是 像FileMonitor一样。从卷A: 到卷Z:都尝试挂接一遍
VOID
SfAttachToMountedVolume( )
{
WCHAR filename[] = L"//DosDevices//A://";
UCHAR index = 2;
UNICODE_STRING fileNameUnicodeString;
NTSTATUS ntStatus;
for( ;index < 26 ; index ++ )
{
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatus;
HANDLE ntFileHandle;
PFILE_OBJECT f ileObject;
PDEVICE_OBJECT volumeDevice;
filename[12] = (CHAR) ('A'+index);
RtlInitUnicodeString( &fileNameUnicodeString, filename );
InitializeObjectAttributes( &objectAttributes,
&fileNameUnicodeString,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE ,
NULL,
NULL
);
ntStatus = ZwCreateFile( &ntFileHandle,
SYNCHRONIZE|FILE_ANY_ACCESS,
&objectAttributes,
&ioStatus, NULL,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
F ILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE,
NULL,
0 );
if( !NT_SUCCESS( ntStatus ) )
{
continue;
}
ntStatus = ObReferenceObjectByHandle( ntFileHandle,
FILE_READ_DATA,
NULL,
KernelMode,
&fileObject,
NULL );
if( !NT_SUCCESS( ntStatus ))
{
ZwClose( ntFileHandle );
continue;
}
volumeDevice = IoGetRelatedDeviceObject( fileObject );
if( !volumeDevice )
{
ObDereferenceObject( fileObject );
ZwClose( ntFileHandle );
continue;
}
if( volumeDevice->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM )
{
continue;
}
SfFsNotification( volumeDevice, TRUE );
最后。如果想控制插入U盘,移动硬盘,光盘,别忘了把过滤器挂接到文件系统设备对象上哦!
VOID
SfAttachToFileSystem( )
{
PFILE_OBJECT fileObject;
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
UNICODE_STRING strDeviceName;
RtlInitUnicodeString( &strDeviceName, L"//Fat" );
status = IoGetDeviceObjectPointer( &strDeviceName,
FILE_READ_ATTRIBUTES,
&fileObject,
&deviceObject
);
if( NT_SUCCESS( status ) )
{
ObDereferenceObject( fileObject );
SfFsNotification( deviceObject, TRUE);
}
RtlInitUnicodeString( &strDeviceName, L"//Ntfs" );
status = IoGetDeviceObjectPointer( &strDeviceName,
FILE_READ_ATTRIBUTES,
&fileObject,
&deviceObject
);
if( NT_SUCCESS( status ) )
{
ObDereferenceObject( fileObject );
SfFsNotification( deviceObject, TRUE);
}
RtlInitUnicodeString( &strDeviceName, L"//Cdfs" );
status = IoGetDeviceObjectPointer( &strDeviceName,
FILE_READ_ATTRIBUTES,
&fileObject,
&deviceObject
);
if( NT_SUCCESS( status ) )
{
ObDereferenceObject( fileObject );
SfFsNotification( deviceObject, TRUE);
}
}