test001
驱动小牛
驱动小牛
  • 注册日期2006-11-12
  • 最后登录2008-11-07
  • 粉丝0
  • 关注0
  • 积分990分
  • 威望170点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
阅读:1322回复:6

strpic请进!

楼主#
更多 发布于:2007-04-13 11:30
  你好!
   我最近刚刚开始学习文件过滤驱动方面的资料,看了你关于“禁止指定目录中一切文件操作”的帖子,于是我就按照你的代码对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。
xx_qiang
驱动小牛
驱动小牛
  • 注册日期2004-07-30
  • 最后登录2017-02-27
  • 粉丝2
  • 关注1
  • 积分31分
  • 威望249点
  • 贡献值0点
  • 好评度171点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2007-04-27 16:13
因为和标题不符合,所以只能做在板凳上看cn~~~~~~~~~~~~~~~`
test001
驱动小牛
驱动小牛
  • 注册日期2006-11-12
  • 最后登录2008-11-07
  • 粉丝0
  • 关注0
  • 积分990分
  • 威望170点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
板凳#
发布于: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函数里修改。请指教。
   多谢!
test001
驱动小牛
驱动小牛
  • 注册日期2006-11-12
  • 最后登录2008-11-07
  • 粉丝0
  • 关注0
  • 积分990分
  • 威望170点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-04-13 16:15
我现在就去试一试!
多谢!
strpic
驱动小牛
驱动小牛
  • 注册日期2006-11-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望238点
  • 贡献值0点
  • 好评度156点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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;
//  }

}
test001
驱动小牛
驱动小牛
  • 注册日期2006-11-12
  • 最后登录2008-11-07
  • 粉丝0
  • 关注0
  • 积分990分
  • 威望170点
  • 贡献值0点
  • 好评度169点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-04-13 14:40
引用第1楼devia2007-04-13 12:59发表的“”:
代码中有两个问题需要处理:

1.wcsncmp是不区分大小写的,所有比较可能会有问题;

2.你得到文件名是在底层FSD返回之后,所以简单返回STATUS_ACCESS_DENY会存在对象泄漏,
.......



我试了一下,跟大小写好像没什么关系,另外,
弱弱的问一下,怎么样CANCEL掉CREATE操作?
多谢!
devia
论坛版主
论坛版主
  • 注册日期2005-05-14
  • 最后登录2016-04-05
  • 粉丝3
  • 关注0
  • 积分1029分
  • 威望712点
  • 贡献值1点
  • 好评度555点
  • 原创分8分
  • 专家分4分
6楼#
发布于:2007-04-13 12:59
代码中有两个问题需要处理:

1.wcsncmp是不区分大小写的,所有比较可能会有问题;

2.你得到文件名是在底层FSD返回之后,所以简单返回STATUS_ACCESS_DENY会存在对象泄漏,
   并可能对应用层造成应用层行为异常(比如说文件夹无法删除等问题),所以在你失败返回之前
   应该CANCEL掉CREATE操作;
人总在矛盾中徘徊。。。
游客

返回顶部