slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
阅读:4252回复:13

总结:关于文件夹地隐藏。

楼主#
更多 发布于:2004-02-07 22:22
1、返回的列表中只有一项并且这一项就是需要隐藏的项同时ReturnSingleEntry又为TRUE时怎么办?

  1)、Coolice采用重新调用ZwQueryDirectoryFile()的方法,不过这种方法需要考虑重入问题。
  2)、VCMFC通过对根目录进行特别处理来实现隐藏,不过他没有给出代码,具体方法我也不清楚。

  还有另外一种的方法,那就是重新构造IRP查询。Coolice也提到了这种方法,不过他也没有代码。OK,下面就是这种方法的代码:

  //
  // 执行隐藏操作
  //
  bool bNeedReQuery;
  bool bReturnSingleEntry;

  bReturnSingleEntry = ((IrpStack->Flags & SL_RETURN_SINGLE_ENTRY)
              == SL_RETURN_SINGLE_ENTRY
              );

  while(true)
  {  
    //
    // 在SfHideFile()中判断是否符合上述条件,如果符合则设置bNeedReQuery为TRUE然后直接返回。
    //
    Status = SfHideFile(
          &FullDirName,
          Irp->UserBuffer,
          IrpStack->Parameters.QueryFile.Length,
          bReturnSingleEntry,
          &bNeedReQuery
          );
    if(!bNeedReQuery)
    {
      break;
    }

    //
    // 如果欲隐藏的文件恰好是第一项,这时候只能通过重新查询来实现隐藏。
    //
    Status = SfReissueIrp(Irp,DeviceObject->StackSize + 2,DevExt);
    if(Status != STATUS_SUCCESS)
    {
      break;
    }
  }


  //---------------------------------------------------------------------------
  //
  // 构造新的IRP来继续查询
  //
  NTSTATUS
  SfReissueIrp(
    IN PIRP Irp,
    IN int StackSize,
    IN PSFILTER_DEVICE_EXTENSION DevExt
    )
  {
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpStack;
    PIRP NewIrp;
    PIO_STACK_LOCATION NextIrpStack;

    NewIrp = IoAllocateIrp(StackSize,false);
    if(NewIrp != NULL)
    {
      //
      // 设置同步事件
      //
      KEVENT WaitEvent;

      KeInitializeEvent(&WaitEvent,SynchronizationEvent,false);
  
      //
      // 设置IRP
      //
      NewIrp->UserEvent = NULL;
  
      NewIrp->AssociatedIrp.SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
      NewIrp->UserBuffer = Irp->UserBuffer;

      NewIrp->Tail.Overlay.Thread = PsGetCurrentThread();
      NewIrp->RequestorMode = Irp->RequestorMode;
      NewIrp->Flags = Irp->Flags & (~IRP_ASSOCIATED_IRP);
  
      //
      // 设置IO堆栈
      //
      IrpStack = IoGetCurrentIrpStackLocation(Irp);
      NextIrpStack = IoGetNextIrpStackLocation(NewIrp);
  
      *NextIrpStack = *IrpStack;
  
      NextIrpStack->CompletionRoutine = SfDirectoryControlCompletion;
      NextIrpStack->Context = &WaitEvent;
  
      //
      // 发送新的IRP到下层FSD
      //
      Status = IoCallDriver(DevExt->AttachedToDeviceObject,NewIrp);
      if(Status == STATUS_PENDING)
      {
        KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL);
  
        Status = NewIrp->IoStatus.Status;
      }

      //
      // 释放IRP
      //
      IoFreeIrp(NewIrp);
    }
    else
    {
      Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return Status;
  }


2、那就是要隐藏的文件在返回缓冲中不是第一项时怎么隐藏?

  我使用“隐藏”来搜索了本分论坛的贴子,在有关隐藏文件夹地讨论中,发现几乎99.9999%的FSFD Writer都使用与VCMFC相同的方法,那就是不停的Move Memory …:),实际上除了第一项需要Move以外,后面所有项地隐藏都是不需要Move的,直接更改一个ULONG值就可以了,一律Move只会对系统性能产生影响。虽然现在CPU已经是2、3、4G了(Sorry,具体是多少不清楚),不过追求最好的性能应该是一个程序员最基本的追求吧?

  //
  // 1、第一项匹配
  //
  if(...)
  {
  }

  //
  // 2:最后一项匹配
  //
  else if(pDirInfo->NextEntryOffset == 0)
  {
    pPrevDirInfo->NextEntryOffset = 0;
  }

  //
  // 3:中间项匹配
  //
  else
  {
    //
    // 隐藏中间项目时不需要调整pPrevDirInfo的值
    //
    bMustAdjustPrevDirInfo = false;

    pPrevDirInfo->NextEntryOffset += pDirInfo->NextEntryOffset;
  }

  //
  // ........ // Do something here
  //

  //
  // 是否需要调整pPrevDirInfo的值?(隐藏中间项目时不需要)
  //
  if(bMustAdjustPrevDirInfo)
  {
    pPrevDirInfo = pDirInfo;
  }

  pDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)pDirInfo + pDirInfo->NextEntryOffset);


3、最最重要的一点,那就是我上面的贴出的代码是不能直接Copy & Paste & Compile的,其中道理我想你自己应该明白。


2004-1-30开始学习文件系统驱动开发,直接着手的第一个问题就是把以前通过Hook ZwQueryDirectoryFile()来实现文件夹隐藏的驱动重新使用FSFD来实现。说来惭愧,使用了8天时间才彻底搞定。

题外话:SFilter在2K上面也是可以动态加载的,使用一些Trick就可以了。如果老是只听MS的那些工程师的话,那玩驱动编程岂不是少了许多乐趣?

最后,如果你认为我的总结对你还有一个点帮助,就请up一个这个贴子



[编辑 -  2/7/04 by  slwqw]

[编辑 -  2/7/04 by  slwqw]

最新喜欢:

gongliyugongli... cyliucyliu
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-02-09 10:03
不需要重新构造一个irp,只需要把原来的irp往下传就可以了


我试过了这种方法,结果产生了MULTIPLE_REQUEST_COMPLETION BugCheck,也就是说IRP被完成了两次。如果要解决这个问题那还得做别地处理。不如重新构造一个IRP方便,不用考虑那么多。
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-02-11 18:06
其实最大的损耗不在这里,在匹配规则表的时间,那将是最大的地方。


同意!

假设一个目录下面存在50项,需要隐藏其中的4项,最坏情况下需要匹配“49 + 48 + 47 + 46”次,实在受不了 :( :( :(

如果待隐藏的目录或者文件中“不包含通配符”,则使用多模式字符串匹配算法,可以避免这个问题,最多只比较50次即可。

只是不使用通配符又不太现实,烦啊...
游客

返回顶部