tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
阅读:3980回复:12

如何在MjCreate中安全地关闭打开的fileobject?

楼主#
更多 发布于:2004-01-14 10:53
osr上是这样说的:
IoCancelFileOpen is unsafe under any circumstances (the FAQ item should
be changed) - there\'s a front page www.osronline.com article about this
now. The alternative is to have your filter open its own reference to
the file (either a handle with the Zw* APIs through shadow DO\'s or a
file object created with IoCreateStreamFileObject* sent down on the
original IRP_MJ_CREATE IRP), post-process, then close the reference and
send down the original IRP with the original file object.


我下面的代码有没有问题,请大虾指点:
KeInitializeEvent();
IoCopyCurrentIrpStackLocationToNext();
IoSetCompletionRoutine();
IoCallDriver();
KeWaitForSingleObject();

PFILE_OBJECT streamFileObject = NULL;
try
{
streamFileObject = IoCreateStreamFileObject(IrpSp->FileObject, NULL);
}
except (STATUS_INSUFFICIENT_RESOURCES)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}

if (streamFileObject)
{
ObDereferenceObject(streamFileObject);
}

Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;

最新喜欢:

ljmmaryljmmar...
toadwolf
驱动牛犊
驱动牛犊
  • 注册日期2003-11-30
  • 最后登录2013-11-12
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望67点
  • 贡献值0点
  • 好评度26点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-01-15 06:52
http://www.osronline.com/article.cfm?id=219
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-01-15 13:47
http://www.osronline.com/article.cfm?id=219


打不开,:(
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
地板#
发布于:2004-01-15 17:12
    
 
  
Everything Windows Driver Development
 
 
  
    
  
 

    there@citiz.net
 
 
 
 
  
  
    Thu, 15 Jan 2004     9764 members

    
  

    
  
   About This Site
Hector\'s Memos
The NT Insider
The Basics
File Systems
The Online DDK
Downloads
ListServer
Driver Jobs
Store
 
  
 This Site NTDEV NTFSD WINDBG  

  
 
    
  
 
  

 
 

    
THE NT INSIDER  

Emerging Issues in IoCancelFileOpen
The NT Insider, Vol 10, Issue 4, July-August 2003 | Published: 06-May-03| Modified: 27-Aug-03

At the April 2003 Microsoft IFS Plugfest an issue was identified that could arise when two file system filter drivers interact in an unexpected fashion during the processing of IRP_MJ_CREATE.

This situation arises when the lower filter performs an IRP_MJ_READ or IRP_MJ_WRITE operation after the IRP_MJ_CREATE has been satisfied by the underlying file system and then the higher filter calls IoCancelFileOpen because it has decided to disallow the file open.

What actually happens is that the lower filter\'s call will cause the virtual memory system (cache manager and memory manager) to increment the reference count of the file object passed in the IRP_MJ_READ.  If this is the IRP_MJ_READ from the original IRP_MJ_CREATE, the reference count on that file object is incremented.

When the higher filter calls IoCancelFileOpen the I/O Manager issues an IRP_MJ_CLEANUP and IRP_MJ_CLOSE down to the lower filter and then to the file system - as if the reference count had in fact dropped to zero.  The higher filter then returns an error to the I/O Manager (or other OS component) and that component then discards the file object, even though there is a dangling reference from the virtual memory system.  Thus, later when the virtual memory system releases its reference to the \"file object\" it is now acting on a potentially arbitrary location in memory.  This can trigger random failures.

In the initial analysis, Microsoft developers indicated that this appears to be a bug in IoCancelFileOpen and the way it is used within Windows. On further investigation, there does not appear to be a fix that can be made that would only affect IoCancelFileOpen to address 100% of the issues that can arise, but Microsoft developers are exploring this issue in search of  a good solution.

OSR developers have suggested that in fact this is a bug in the lower filter because it is never safe to perform a non-cached I/O call IRP_MJ_READ or IRP_MJ_WRITE with the file object from the IRP_MJ_CREATE.  This is because some paths within the file system create fake (stack based) file objects in order to improve performance for operations that would not invoke the virtual memory system. Note: with NTFS, a non-cached I/O request is not honored in the case of compressed files.  Other (third party) file systems may similarly ignore a request for non-cached I/O.

At the present time our suggested work-around is for the filter to use IoCreateStreamFile, IoCreateStreamFileLite, or IoCreateStreamFileEx to create its own stream file object.  This new stream file object may then be used when setting up the next I/O stack location in the IRP.  The filter should then forward the IRP to the next driver synchoronously (this is normally done by blocking and waiting on a notification event that is set in the completion routine).  The stream file object may then be used for IRP_MJ_READ and IRP_MJ_WRITE operations safely.  When the filter is done using the stream file object, it may be dereferenced (potentially causing an IRP_MJ_CLEANUP and IRP_MJ_CLOSE) and Windows will delete it when appropriate.  If the original create is to be allowed to proceed, the IRP can then be sent (with the original file object) to the underlying driver for further processing.  Initial reports from developers are promising regarding this work around.

Regardless, we know this is an emerging issue.  Stay tuned for further information.

Additional Information (May 9, 2003)

Microsoft has indicated that the following calls may use stack-based file objects:

NtDeleteFile
NtQueryAttributesFile
NtQueryFullAttributesFile
IoFastQueryNetworkAttributes

And that these fake file objects may appear for the following operations:

IRP_MJ_CREATE
IRP_MJ_CLEANUP
IRP_MJ_CLOSE
IRP_MJ_QUERY_INFORMATION
FastIoQueryOpen
FastIoQueryBasicInfo
FastIoQueryStandardInfo
FastIoQueryNetworkOpenInfo

Further, the information from the Microsoft team indicates that this situation is unlikely to change in the forseeable future.

The previously described solution remains OSR\'s suggested solution.

Additional Information (July 10, 2003)

The Microsoft filter driver team has provided an alternative solution as well:

To work around this issue, the filter doing cached I/O to the file during IRP_MJ_CREATE processing should do the following:

Check to see if the file object address is within the current stack limits (IoGetStackLimits)
If the file object address is within the current stack limits, the filter should allocate its own file object (IoCreateStreamFileObject, or IoCreateStreamFileObjectLite), pass this stream file object down to the file system to be opened, then do the cached I/O against this file object.  This is a well-formed file object which will be cleaned up safely if this is the file object referenced by either the cache manager or the memory manager.
Here is the pseudo code for a filter that cancels create operations.  In your IRP_MJ_CREATE dispatch routine, before the operation has been passed down to the file system, if this is a create that you may wish to cancel, do the following:

//

// Pseudo code assumptions:

//

// Variables:

// NameToOpen
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-01-16 09:28
感谢 wowocock !正在消化中...
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-01-16 09:40
继续请教: :D
DDK 中说:
File system filter driver writers should note that IoCreateStreamFileObject causes an IRP_MJ_CLEANUP request to be sent to the file system driver stack for the volume.

请问IRP_MJ_CLEANUP是何时发出的,在IoCreateStreamFileObject中发出,还是后面调用ObDereferenceObject时发出??
qwdrv
驱动大牛
驱动大牛
  • 注册日期2004-03-19
  • 最后登录2005-12-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-03-25 16:02
osr上是这样说的:
IoCancelFileOpen is unsafe under any circumstances (the FAQ item should
be changed) - there's a front page www.osronline.com article about this
now. The alternative is to have your filter open its own reference to
the file (either a handle with the Zw* APIs through shadow DO's or a
file object created with IoCreateStreamFileObject* sent down on the
original IRP_MJ_CREATE IRP), post-process, then close the reference and
send down the original IRP with the original file object.


我下面的代码有没有问题,请大虾指点:
KeInitializeEvent();
IoCopyCurrentIrpStackLocationToNext();
IoSetCompletionRoutine();
IoCallDriver();
KeWaitForSingleObject();

PFILE_OBJECT streamFileObject = NULL;
try
{
streamFileObject = IoCreateStreamFileObject(IrpSp->FileObject, NULL);
}
except (STATUS_INSUFFICIENT_RESOURCES)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}

if (streamFileObject)
{
ObDereferenceObject(streamFileObject);
}

Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;

重大bug,会bugcheck的
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
7楼#
发布于:2008-05-06 16:51
不错,正解之急
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
8楼#
发布于:2009-09-20 20:37
描述

在打开文件后根据条件决定是否关闭文件打开。

但是使用了IoCreateStreamFileObjectLite怎么去操作呢?

SfCreate()
{
      streamFileObject = IoCreateStreamFileObject(IrpSp->FileObject, NULL);

      IoCallDriver(streamFileObject );

      if(可以打开文件)
             status = IoCallDriver(FileObject );
      else
              status = STATUS_ACCESS_DENIED;

     ObDereferenceObject(streamFileObject);

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}

可是这样处理是错误的,一旦调用了status = IoCallDriver(FileObject ); 就发生:

(368)SfRead : \Device\HarddiskVolume4 (\temp\temp1.txt)
Access violation - code c0000005 (!!! second chance !!!)
Fastfat!FatFsdRead+0x3e:
f7c4c640 66813b0205      cmp     word ptr [ebx],502h
错误

上面的SfCreate流程应该怎么处理?
走走看看开源好 Solaris vs Linux
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
9楼#
发布于:2009-09-21 12:05
问题解决
走走看看开源好 Solaris vs Linux
yandong_8212
驱动小牛
驱动小牛
  • 注册日期2006-07-28
  • 最后登录2011-02-11
  • 粉丝0
  • 关注0
  • 积分1046分
  • 威望464点
  • 贡献值1点
  • 好评度173点
  • 原创分0分
  • 专家分1分
10楼#
发布于:2009-09-21 12:36
我贴一部分代码给你参考:
tempFileObject = IoCreateStreamFileObjectLite(NULL, VolumeDeviceObject);
            if (!tempFileObject)
            {
                ObDereferenceObject(tempFileObject);
            }
ASSERT(tempFileObject);
            RtlZeroMemory(tempFileObject, sizeof(FILE_OBJECT));
            tempFileObject->Type = IO_TYPE_FILE;
            tempFileObject->Size = sizeof(FILE_OBJECT);
            tempFileObject->DeviceObject = pStorage->VolumeDeviceObject;
            tempFileObject->Flags = FO_SYNCHRONOUS_IO;
            foBuffer = AllocatePool(NonPagedPool, MAX_PATH, __LINE__);
            RtlCopyMemory(foBuffer, usFullPath.Buffer + 2, usFullPath.Length - 2 * sizeof(WCHAR));
            RtlInitUnicodeString(&tempFileObject->FileName, (PWCHAR)foBuffer);
            KeInitializeEvent(&tempFileObject->Lock, SynchronizationEvent, FALSE);
            KeInitializeEvent(&tempFileObject->Event, NotificationEvent, FALSE);

            //初始化irp
            irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
            if (irp == NULL)
            {
                status = STATUS_INSUFFICIENT_RESOURCES;

                __leave;
            }

            irp->MdlAddress = NULL;
            irp->Flags |= IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
            irp->RequestorMode = KernelMode;
            irp->UserIosb = &pWorkItem->IoStatus;
            irp->UserEvent = &pWorkItem->evUserEvent;
            irp->PendingReturned = FALSE;
            irp->Cancel = FALSE;
            irp->CancelRoutine = NULL;
            irp->Tail.Overlay.AuxiliaryBuffer = NULL;
            irp->Tail.Overlay.OriginalFileObject = tempFileObject;

            // 初始化安全属性

            status = SeCreateAccessState(   &pWorkItem->u.CREATE.accessState,
                                            &pWorkItem->u.CREATE.auxData,
                                            pWorkItem->u.CREATE.DesiredAccess,
                                            IoGetFileObjectGenericMapping());

            if (!NT_SUCCESS(status))
            {
                IoFreeIrp(irp);
                ObDereferenceObject(tempFileObject);
                __leave;
            }

            pWorkItem->u.CREATE.SecurityContext.SecurityQos = NULL;
            pWorkItem->u.CREATE.SecurityContext.AccessState = &pWorkItem->u.CREATE.accessState;
            pWorkItem->u.CREATE.SecurityContext.DesiredAccess = pWorkItem->u.CREATE.DesiredAccess;
            pWorkItem->u.CREATE.SecurityContext.FullCreateOptions = 0;

            //初始化IrpStack
            irpSp = IoGetNextIrpStackLocation(irp);
            irpSp->MajorFunction = IRP_MJ_CREATE;
            irpSp->Parameters.Create.SecurityContext = &pWorkItem->u.CREATE.SecurityContext;
            irpSp->Parameters.Create.Options = pIrpStack->Parameters.Create.Options;
            irpSp->Parameters.Create.FileAttributes = pIrpStack->Parameters.Create.FileAttributes;
            irpSp->Parameters.Create.ShareAccess = pIrpStack->Parameters.Create.ShareAccess;
            irpSp->Parameters.Create.EaLength = 0;

            pWorkItem->FileObject = tempFileObject;
            irpSp->FileObject = tempFileObject;
            irpSp->DeviceObject = pStorage->DeviceObject;

            IoSetCompletionRoutine(irp,
                                   IoCompletionRoutine,
                                   NULL,
                                   TRUE,
                                   TRUE,
                                   TRUE);

            pWorkItem->u.CREATE.pIrp = irp;

            status = IoCallDriver(pStorage->DeviceObject, pWorkItem->u.CREATE.pIrp);

                if (status == STATUS_PENDING)
                {
                    KeWaitForSingleObject(&pWorkItem->evUserEvent, Executive, KernelMode, TRUE, NULL);
                    status = pWorkItem->IoStatus.Status;
                }

                ObReferenceObject(pWorkItem->FileObject);
商务MSN:YanDong_8212@163.com
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
11楼#
发布于:2009-09-21 13:37
非常感谢yandong_8212 ,但我解本还是按照我上面提到流程去写了,但是不知道是否正确。

znsoft说osr上的说得方法会蓝屏,有过此类经验的人也给各说法阿。
走走看看开源好 Solaris vs Linux
yandong_8212
驱动小牛
驱动小牛
  • 注册日期2006-07-28
  • 最后登录2011-02-11
  • 粉丝0
  • 关注0
  • 积分1046分
  • 威望464点
  • 贡献值1点
  • 好评度173点
  • 原创分0分
  • 专家分1分
12楼#
发布于:2009-09-21 17:55
可能是计数问题,应该是CREATE成功了再DEREFER吧.或者自己REFER之后. 代码你就随便看看吧.
商务MSN:YanDong_8212@163.com
游客

返回顶部