lhzh114
驱动牛犊
驱动牛犊
  • 注册日期2004-02-20
  • 最后登录2008-12-27
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望37点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
阅读:1996回复:10

讨论 tooflat 的代码,100 分伺候

楼主#
更多 发布于:2004-12-24 09:21
NTSTATUS
ProcessHiddenFile(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PIO_STACK_LOCATION IrpSp
)
{
NTSTATUS status;
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    KEVENT event;
    PFILE_BOTH_DIR_INFORMATION QueryBuffer = NULL;
    PFILE_BOTH_DIR_INFORMATION PreQueryBuffer = NULL;
    ULONG offset = 0;
    ULONG pos = 0;
    ULONG len = 0;
    ULONG newlen = 1;
    WCHAR file[] = L"TEST.TXT";

KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, HiddenFileCompletion, &event, TRUE, TRUE, TRUE);
status = IoCallDriver(pdx->NextDeviceObject, Irp);
 
if (STATUS_PENDING == status)
{
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
}


   while (1)
   {
    len = IrpSp->Parameters.QueryFile.Length;    //ifs kit 2000说明应该用QueryDirectory吧,文档里没有QueryFile?
    newlen = len;
    QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer;
    PreQueryBuffer = QueryBuffer;

    if ((!QueryBuffer) || (QueryBuffer->NextEntryOffset > len))  //什么时候QueryBuffer->NextEntryOffset > len ?
    {
        IoSkipCurrentIrpStackLocation(Irp);
        return IoCallDriver(pdx->NextDeviceObject, Irp);
    }

    do
    {
        offset = QueryBuffer->NextEntryOffset;
// 过滤规则
if ((QueryBuffer->FileNameLength > 0) && (_wcsicmp(QueryBuffer->FileName, file) == 0))
  {
          if (0 == offset) // the last one
 {
             PreQueryBuffer->NextEntryOffset = 0;
             newlen = pos;
 }
          else
 {
             if (PreQueryBuffer != QueryBuffer)
             {
                PreQueryBuffer->NextEntryOffset += offset;
             }
             else // the first one
             {
                RtlMoveMemory((PUCHAR) QueryBuffer, (PUCHAR) QueryBuffer + offset, len - pos - offset);
             }
             newlen -= offset;
 }
          break;
  }
       pos += offset;
       PreQueryBuffer = QueryBuffer;
       QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR) QueryBuffer + offset);
    } while (0 != offset);

  

    if (0 == newlen)
    {
        KeResetEvent(&event);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, HiddenFileCompletion, &event, TRUE, TRUE, TRUE);
status = IoCallDriver(pdx->NextDeviceObject, Irp);
 
if (STATUS_PENDING == status)                               //为何再次把irp发送到下层后等待?
{
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
}

       if (0 == Irp->IoStatus.Information)
       {
        break;
       }
    }
    else
    {
       Irp->IoStatus.Information = newlen;
       break;
    }
   } //while(1)

   IoCompleteRequest(Irp, IO_NO_INCREMENT);
   return Irp->IoStatus.Status;                              //完成irp后还可以用 Irp->IoStatus.Status ?
}

NTSTATUS
HiddenFileCompletion(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
)
{
  
   UNREFERENCED_PARAMETER(DeviceObject);
   UNREFERENCED_PARAMETER(Irp);                             //此调用起什么作用?

   if (Irp->PendingReturned)
   {
      KeSetEvent((PRKEVENT) Context, IO_NO_INCREMENT, FALSE);
   }
   return STATUS_MORE_PROCESSING_REQUIRED;  
  
}

//我是新手,请各路高手指点迷津
fslife
驱动大牛
驱动大牛
  • 注册日期2004-06-07
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望49点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-12-24 09:57
这个代码好像是参考SFILTER的吧

1“为何再次把irp发送到下层后等待?”
应该是利用事件同步完成例程吧,也就是在IoCompleteRequest(Irp, IO_NO_INCREMENT)前保证完成例程已经OK了。

2“完成irp后还可以用 Irp->IoStatus.Status ?”
我也觉得有点问题。
在交流中学习。。。
snowStart
驱动老牛
驱动老牛
  • 注册日期2004-04-06
  • 最后登录2011-06-02
  • 粉丝0
  • 关注0
  • 积分95分
  • 威望19点
  • 贡献值177点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-12-24 13:13
关注学习中...
学习,关注,交流中... [email=fengyu@163.com]Email:snowstarth@163.com[/email] [url]http://bbs.zndev.com/?a=snowStart[/url]
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-12-27 10:21
这个代码好像是参考SFILTER的吧

1“为何再次把irp发送到下层后等待?”
应该是利用事件同步完成例程吧,也就是在IoCompleteRequest(Irp, IO_NO_INCREMENT)前保证完成例程已经OK了。

================================================
如果所有目录项都被过滤掉了,需要将该irp再向下传,然后再对返回的目录项进行处理

2“完成irp后还可以用 Irp->IoStatus.Status ?”
我也觉得有点问题。

================================================
是有问题




什么时候QueryBuffer->NextEntryOffset > len ?
================================================
容错性处理而已,应该不会有这种情况发生


UNREFERENCED_PARAMETER(Irp); //此调用起什么作用?
================================================
原来的目的是不让编译器发生警告,这里不需要

[编辑 -  12/27/04 by  tooflat]
lhzh114
驱动牛犊
驱动牛犊
  • 注册日期2004-02-20
  • 最后登录2008-12-27
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望37点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-12-27 11:38
tooflat大侠:

您这段代码别处还有问题吗?请指教!
我用上后加载总是 重新启动

能QQ交流吗?50994497
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-12-27 17:47
tooflat大侠:

您这段代码别处还有问题吗?请指教!
我用上后加载总是 重新启动

能QQ交流吗?50994497


还没有发现其他问题,你可以跟踪一下是什么地方蓝屏,
我不用QQ
lhzh114
驱动牛犊
驱动牛犊
  • 注册日期2004-02-20
  • 最后登录2008-12-27
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望37点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-01-12 17:31
这样调用的:
NTSTATUS status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation( Irp );

if ((irpsp->MinorFunction) == IRP_MN_QUERY_DIRECTORY )
{
       return ProcessHiddenFile(DeviceObject,Irp,irpsp);
}
else
{
  IoSkipCurrentIrpStackLocation(Irp);
  return IoCallDriver(pdx->NextDeviceObject, Irp);
}


调用QueryBuffer->NextEntryOffset,跟踪发现处理一些个IRP时访问QueryBuffer->NextEntryOffset提示Access Violation,然后蓝屏→重启
不知什么原因?
win2000 + ifs kit 2k
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-01-12 23:01
是不是QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer;
这句代码有问题,我原来的代码前面对RequestMode有判断,如果是KernelMode,就直接下发了,如果是KernelMode,那么buffer就不在Irp->UserBuffer,应该在Irp->MdlAddress
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-01-13 08:56
是不是QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer;
这句代码有问题,我原来的代码前面对RequestMode有判断,如果是KernelMode,就直接下发了,如果是KernelMode,那么buffer就不在Irp->UserBuffer,应该在Irp->MdlAddress


看了一下DDK,缓冲区就应该在UserBuffer中,不清楚为什么你那边为出现这个问题
lhzh114
驱动牛犊
驱动牛犊
  • 注册日期2004-02-20
  • 最后登录2008-12-27
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望37点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-01-13 15:46
这是源代码,2000下的sFilter,帮忙看一下,先谢谢了!
附件名称/大小 下载次数 最后更新
2005-01-13_sfilter.c (93KB)  43
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2005-01-14 21:15
while (1)
   {

//增加这句代码试试
    pos = 0;

        len = IrpSp->Parameters.QueryFile.Length;
    newlen = len;
    QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer;
    PreQueryBuffer = QueryBuffer;
游客

返回顶部