阅读:1321回复:6
strpic请进!
你好!
我最近刚刚开始学习文件过滤驱动方面的资料,看了你关于“禁止指定目录中一切文件操作”的帖子,于是我就按照你的代码对SfCreate进行了修改,如下: NTSTATUS SfCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This function filters create/open operations. It simply establishes an I/O completion routine to be invoked if the operation was successful. Arguments: DeviceObject - Pointer to the target device object of the create/open. Irp - Pointer to the I/O Request Packet that represents the operation. Return Value: The function value is the status of the call to the file system's entry point. --*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; PUNICODE_STRING name; GET_NAME_CONTROL nameControl; wchar_t* myProtectPath = L"\\Device\\HarddiskVolume1\\test\\"; PAGED_CODE(); // // If this is for our control device object, don't allow it to be opened. // if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { // // Sfilter doesn't allow for any communication through its control // device object, therefore it fails all requests to open a handle // to its control device object. // // See the FileSpy sample for an example of how to allow creates to // the filter's control device object and manage communication via // that handle. // Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; } ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); // // If debugging is enabled, do the processing required to see the packet // upon its completion. Otherwise, let the request go with no further // processing. // if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION | SFDEBUG_GET_CREATE_NAMES| SFDEBUG_DISPLAY_CREATE_NAMES )) { // // Don't put us on the stack then call the next driver // IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } else { KEVENT waitEvent; // // Initialize an event to wait for the completion routine to occur // KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); // // Copy the stack and set our Completion routine // IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine( Irp, SfCreateCompletion, &waitEvent, TRUE, TRUE, TRUE ); // // Call the next driver in the stack. // status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); irpSp = IoGetCurrentIrpStackLocation( Irp ); name = SfGetFileName( irpSp->FileObject, Irp->IoStatus.Status, &nameControl ); if( wcsncmp( name->Buffer, myProtectPath, wcslen( myProtectPath ) ) == 0 ) { DbgPrint( "Access Denied: %wZ\n", name ); SfGetFileNameCleanup( &nameControl ); Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return Irp->IoStatus.Status; } // // Wait for the completion routine to be called // if (STATUS_PENDING == status) { NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); ASSERT(STATUS_SUCCESS == localStatus); } // // Verify the IoCompleteRequest was called // ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status)); // // Retrieve and display the filename if requested // if (FlagOn(SfDebug, (SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES))) { SfDisplayCreateFileName( Irp ); } // // Save the status and continue processing the IRP // status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } } 可是编译完了以后,却并没有实现对硬盘下的test目录中一切文件操作的禁止,不知道是什么原因?我用drivermonitor查看生成的驱动,然后对test目录下的文件进行操作,看不到任何的打印信息,不知道是什么原因?请你给我一些指导,多谢! 我的环境是WinXP,WinDDK\3790。 |
|
沙发#
发布于:2007-04-13 12:59
代码中有两个问题需要处理:
1.wcsncmp是不区分大小写的,所有比较可能会有问题; 2.你得到文件名是在底层FSD返回之后,所以简单返回STATUS_ACCESS_DENY会存在对象泄漏, 并可能对应用层造成应用层行为异常(比如说文件夹无法删除等问题),所以在你失败返回之前 应该CANCEL掉CREATE操作; |
|
|
板凳#
发布于:2007-04-13 14:40
引用第1楼devia于2007-04-13 12:59发表的“”: 我试了一下,跟大小写好像没什么关系,另外, 弱弱的问一下,怎么样CANCEL掉CREATE操作? 多谢! |
|
地板#
发布于:2007-04-13 15:30
你的代码没有执行到,默认情况下执行的是if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION|SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES )) 中的代码,要执行else下的代码,需要修改ErrorControl的值,或者按我修改的做也可以。
NTSTATUS SfCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION irpSp; PUNICODE_STRING name; GET_NAME_CONTROL nameControl; wchar_t* myProtectPath = L"\\Device\\HarddiskVolume1\\test\\"; KEVENT waitEvent; PAGED_CODE(); // // If this is for our control device object, don't allow it to be opened. // if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { // // Sfilter doesn't allow for any communication through its control // device object, therefore it fails all requests to open a handle // to its control device object. // // See the FileSpy sample for an example of how to allow creates to // the filter's control device object and manage communication via // that handle. // Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; } ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); // // If debugging is enabled, do the processing required to see the packet // upon its completion. Otherwise, let the request go with no further // processing. // /* if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION | SFDEBUG_GET_CREATE_NAMES| SFDEBUG_DISPLAY_CREATE_NAMES )) { // // Don't put us on the stack then call the next driver // IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } else { KEVENT waitEvent; */ // // Initialize an event to wait for the completion routine to occur // KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); // // Copy the stack and set our Completion routine // IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine( Irp, SfCreateCompletion, &waitEvent, TRUE, TRUE, TRUE ); // // Call the next driver in the stack. // status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); irpSp = IoGetCurrentIrpStackLocation( Irp ); name = SfGetFileName( irpSp->FileObject, Irp->IoStatus.Status, &nameControl ); if( wcsncmp( name->Buffer, myProtectPath, wcslen( myProtectPath ) ) == 0 ) { DbgPrint( "Access Denied: %wZ\n", name ); SfGetFileNameCleanup( &nameControl ); Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return Irp->IoStatus.Status; } // // Wait for the completion routine to be called // if (STATUS_PENDING == status) { NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); ASSERT(STATUS_SUCCESS == localStatus); } // // Verify the IoCompleteRequest was called // ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status)); // // Retrieve and display the filename if requested // if (FlagOn(SfDebug, (SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES))) { SfDisplayCreateFileName( Irp ); } // // Save the status and continue processing the IRP // status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; // } } |
|
地下室#
发布于:2007-04-13 16:15
我现在就去试一试!
多谢! |
|
5楼#
发布于:2007-04-27 15:51
strpic:
你好! 上次按照你的代码我试了一下,可是存在你列举的那两个问题(新建文件和复制文件),我又看了以后面的帖子说是把if 中的移到 KeInitializeEvent 之前就行了,可是我试了一下,此时的驱动对文件夹没有任何禁止功能。代码如下: NTSTATUS SfCreate (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { NTSTATUS status; KEVENT waitEvent; PIO_STACK_LOCATION irpSp; PUNICODE_STRING name; GET_NAME_CONTROL nameControl; wchar_t* myProtectPath = L"\\Device\\HarddiskVolume1\\test\\"; PAGED_CODE(); if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; } ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine(Irp,SfCreateCompletion,&waitEvent,TRUE,TRUE,TRUE ); status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); irpSp = IoGetCurrentIrpStackLocation( Irp ); name = SfGetFileName( irpSp->FileObject, Irp->IoStatus.Status, &nameControl ); if( wcsncmp( name->Buffer, myProtectPath, wcslen( myProtectPath ) ) == 0 ) { DbgPrint( "Access Denied: %wZ\n", name ); SfGetFileNameCleanup( &nameControl ); Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return Irp->IoStatus.Status; } if (STATUS_PENDING == status) { NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); ASSERT(STATUS_SUCCESS == localStatus); } ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status)); if (FlagOn(SfDebug, (SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES))) { SfDisplayCreateFileName( Irp ); } status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } 我又试着把if的代码放在其他地方,还是不行,不知道什么原因? 另外,如果我想实现对指定文件的只读控制,即只允许对指定文件的读,其他的操作都禁止,我查了一些相关资料,应该是在SFRead函数里处理,可是我发现sfilter.c里没有SFRead函数,只有SfFastIoRead函数和SfFastIoMdlRead函数,由于在看楚狂人写的文章时,对fastIO介绍的很少,所以我也不太懂,不知道要实现上述功能是自己写一个SFread函数,还是直接在SfFastIoRead函数或SfFastIoMdlRead函数里修改。请指教。 多谢! |
|
6楼#
发布于:2007-04-27 16:13
因为和标题不符合,所以只能做在板凳上看cn~~~~~~~~~~~~~~~`
|
|