fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2538回复:19

很急:关于文件过滤的问题,请帮忙,60分相送

楼主#
更多 发布于:2002-04-12 11:13
我在做一个文件过滤器,具体功能如下:
在硬盘的一个分区建立一个特定的目录,如  \"E:\\test\",当应用程序读此目录下的文件时,比如read 1 :\"E:\\test\\doc.txt\",我要将此读操作转到其他设备,比如一个dvd光驱 2 :\"g:\\doc.txt\".
现在我希望在create例程中用 1 的路径名创建文件,而在read例程中用
2 的路径名读数据,这样是否可行?是否要在read例程中
create (g:\\doc.txt)呢?为了应用程序得到 2 的数据,我将如何构造新的irp包?对旧的irp包我得作怎样的处理?
请各位指点,越清楚越好。

最新喜欢:

aasa2aasa2 IammeIamme
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-04-12 11:29
我的开发环境是win 2000
过滤器是挂接在ntfs之上的
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-04-12 12:29
我在做一个文件过滤器,具体功能如下:
在硬盘的一个分区建立一个特定的目录,如  \"E:\\test\",当应用程序读此目录下的文件时,比如read 1 :\"E:\\test\\doc.txt\",我要将此读操作转到其他设备,比如一个dvd光驱 2 :\"g:\\doc.txt\".
现在我希望在create例程中用 1 的路径名创建文件,而在read例程中用
2 的路径名读数据,这样是否可行?是否要在read例程中
create (g:\\doc.txt)呢?为了应用程序得到 2 的数据,我将如何构造新的irp包?对旧的irp包我得作怎样的处理?
请各位指点,越清楚越好。
 

    这样是不行的,因为你的文件\"E:\\test\\doc.txt\"和你欲重定向的文件dvd光驱\"g:\\doc.txt\"一般来说不是同一个文件系统,使用的驱动程序也不同,就此这一种情况来说,你的文件系统是NTFS,而重定向目标FSD则是CDFS或者DVDFS.这并不是一个一般的过滤驱动。
    但一定是可以实现的,我的想法是这样:
    拦截到你指定的目录的访问非常简单,你一定已经掌握了。至拦截到以后怎么重定向到另一个FSD,则首先你要得到你重定向的驱动程序创建的设备对象(完整的设备栈);你需要知道这个设备对象的议;然后你要完全重新构造IRP去请求这个服务,并设置完成例程等细节步骤。
    这里不可避免地会调用ZwCreateFile()函数,这很可能会导至重入(IRP_MJ_CREATE),你需要小心地处理这个东西,本站有一篇文章专门探讨了这个问题。
    以上是我的设想,但愿对你有帮助。
Best regards !
Tom_lyd
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-04-12 13:48
谢谢Tom_lyd老兄先,我还想请教:
1.我的那个dvd 设备的文件系统是设置在ntfs之下的,我在重定向时,是否不必修改设备对象了(仍旧发往ntfs)?
2.这个重定向是否可以只在read例程里进行,而不是create例程?
3.那篇文章在哪里呢?怎么找不到?
急呀,明白的请帮忙……

Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-04-12 14:54
谢谢Tom_lyd老兄先,我还想请教:
1.我的那个dvd 设备的文件系统是设置在ntfs之下的,我在重定向时,是否不必修改设备对象了(仍旧发往ntfs)?
2.这个重定向是否可以只在read例程里进行,而不是create例程?
3.那篇文章在哪里呢?怎么找不到?
急呀,明白的请帮忙……

 

    我认为NTFS和CDFS是不存在层次关系的,它们应该是相互独立的。至少硬件上是独立的,彼此文件格式相差很大。否则File monitor怎么就是不HOOK 光驱呢?
    仍旧发往NTFS肯定是错误的,NTFS只能识别NTFS的格式,无法识别DVD的格式,就象它不能识别IOS9660格式一样。所以,你必须得到DVDFS的文件系统设备对象,然后IoCallDriver(DVDFS_DEVICE_OBJECT,pIrp)调用它的服务,当然在此之前你必须构造正确的IRP。另外注意,IoCallDdriver的第一个参数应该是DVDFS的顶层设备,如果它还没有被其他设备过滤,则就是它自身。
    重定向怎么会只在READ例程里进行?你只要读DVD文件吗?不要访问它的属性吗(QUERY_ATTRIBUTE)?没有其它的操作吗?难道不是在每个操作中都要重定向?我觉得得视你的目的而定,也许你只对其中的几个感兴趣。
    请搜索标题“有狠心的同志请看看”,里面有一篇文章讲了IRP_MJ_CREATE重入的问题。

Tom_lyd
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-04-13 15:05
首先恭喜Tom_lyd老兄。其次
依照你的指点,我又重新对我的过滤驱动理解了一下,它看来真的不是普通的过滤功能,得解决分层驱动的重入问题。可我以前从来没有自己分配过irp包,在解决重入时又遇到了几个疑问:
(哎,没办法,老伴催的急,只好厚起脸皮问了,以后有时间一定好好研究)
1.我在我的read例程中构造了新的newirp,得到新目标设备,然后IoCallDriver(),在新设备创建我的文件,这个newirp包如何构造呢?
需要我的read例程得到的oldirp中的什么信息才能保证我在IoCompleteRoutine中利用这个newirp继续IoCallDriver(),调用新设备的read例程,将文件读到用户那里?
2.这样利用IoCompleteRoutine是否可行?我的那个oldirp该怎样处理?
先谢谢了,各位。
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-04-13 15:07
怎么搞的,为什么给不了分了?
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-04-20 16:09
现在我将irp重定向到了新的路径,并且在应用层读到了新设备下的文件。可是,我在关闭应用程序时就死机,softice提示:
break due to KebugCheckEx
error=76 (PROCESS_HAS_LOCKED_PAGES)
我怀疑是那块内存没有释放,可总是找不到正确的地方
请遇到类似问题的大虾指点一下吧,谢谢了……
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-04-20 16:14
要养成在程序退出时释放驱动程序中申请的任何资源,多数是在Unload例程、IRP_MJ_CLOSE中做这些事情。但是有的驱动程序在和它挂接的应用程序关闭时,自身的Unload例程和IRP_MJ_CLOSE不一定能被执行到,可能是由程序自身的错误或者应用程序的某种特殊目的。然而IRP_MJ_CLEANUP却一定会被执行,因此,这里也是一个资源释放的好地方。
Tom_lyd
Supermi
驱动牛犊
驱动牛犊
  • 注册日期2001-10-20
  • 最后登录2014-06-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-04-23 14:59
HI
   我想你已经看过那篇讨论,我在那儿发表了一篇代码,你应该看到了吧,那代码可以避免你创建新的设备,也就是不用老外的办法,
我可以保证我的代码的可靠性,我想知道的是,你要做这种重定向干什么,可以告诉我吗?另外我想知道象你这样研究到文件驱动的人是在哪些单位工作,年龄层次呢?(因为我是大二,我想知道社会的需求,能告诉我吗?)你回答了,我可以给你一些技术提示,我可以告诉你怎样控制读写方向,怎样随心所欲的转换,而且不用调用ZWCREATEFILE,而且避免重入,不必构造irp也能干同样的事 。。。。
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-04-23 15:38
HI
   我想你已经看过那篇讨论,我在那儿发表了一篇代码,你应该看到了吧,那代码可以避免你创建新的设备,也就是不用老外的办法,
我可以保证我的代码的可靠性,我想知道的是,你要做这种重定向干什么,可以告诉我吗?另外我想知道象你这样研究到文件驱动的人是在哪些单位工作,年龄层次呢?(因为我是大二,我想知道社会的需求,能告诉我吗?)你回答了,我可以给你一些技术提示,我可以告诉你怎样控制读写方向,怎样随心所欲的转换,而且不用调用ZWCREATEFILE,而且避免重入,不必构造irp也能干同样的事 。。。。
 

哪篇讨论?哪篇文章?
Tom_lyd
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-04-23 19:32
HI
   我想你已经看过那篇讨论,我在那儿发表了一篇代码,你应该看到了吧,那代码可以避免你创建新的设备,也就是不用老外的办法,
我可以保证我的代码的可靠性,我想知道的是,你要做这种重定向干什么,可以告诉我吗?另外我想知道象你这样研究到文件驱动的人是在哪些单位工作,年龄层次呢?(因为我是大二,我想知道社会的需求,能告诉我吗?)你回答了,我可以给你一些技术提示,我可以告诉你怎样控制读写方向,怎样随心所欲的转换,而且不用调用ZWCREATEFILE,而且避免重入,不必构造irp也能干同样的事 。。。。
 


你的条件倒是很特别嘛。
我的项目实际是为了利用在硬盘上的一个分区作缓冲,来管理多个dvd光驱。我希望能在读取只读文件时应用程序不去访问硬盘缓冲,而是直接去读dvd。大致的你明白了吧。
我研究这个东西纯粹是被老板逼的,来了活,就找个人干呗,我只对文件驱动有个大概的认识,从没做过。
我希望你能告诉我在控制读写方向时,需要注意些什么?我的程序可以转向了,可是在type一个txt文件时会不停的循环调用read例程去读文件的头512字节。这是为什么呢?
另外我想知道你为什么会研究起fsd呢?
eatablecode
驱动牛犊
驱动牛犊
  • 注册日期2002-04-16
  • 最后登录2002-05-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2002-04-24 16:34
似乎有个简单的方法可以解决你的问题,与驱动无关,是在API这一层做。
用程序挂接CreateFile()函数,当CreatFile()的参数是你的磁盘目录下的文件,并且是只读时,就打开DVD上的相应文件,把HANDLE传回去。
大胆假设,小心求[color=red]分[/color]
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2002-04-24 16:57
似乎有个简单的方法可以解决你的问题,与驱动无关,是在API这一层做。
用程序挂接CreateFile()函数,当CreatFile()的参数是你的磁盘目录下的文件,并且是只读时,就打开DVD上的相应文件,把HANDLE传回去。
 

可是如何用程序挂接CreateFile()函数或是ReadFile()函数呢?是不是要做一个服务程序什么的?
eatablecode
驱动牛犊
驱动牛犊
  • 注册日期2002-04-16
  • 最后登录2002-05-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2002-04-24 17:40
你要过滤的是具体的几个应用程序还是系统中的所有程序?如果是后者要稍微麻烦一点。
写一个DLL,插入进程的地址空间,修改模块的IMPORT DESCRIPTOR
大胆假设,小心求[color=red]分[/color]
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2002-04-25 08:51
你要过滤的是具体的几个应用程序还是系统中的所有程序?如果是后者要稍微麻烦一点。
写一个DLL,插入进程的地址空间,修改模块的IMPORT DESCRIPTOR
 

多谢你的指点,可我真的是个菜鸟,对你的提示不太明白。写个dll插入哪个进程的地址空间?怎么插?修改哪个模块的IMPORT DESCRIPTOR?怎么修改?
Supermi
驱动牛犊
驱动牛犊
  • 注册日期2001-10-20
  • 最后登录2014-06-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2002-04-25 15:19
HI
   好的,我了解了。你在TYPE时的不停滚动,是否是因为重入。用SOFTICE检查一下,另外,不用新构造IRP,你截获IRP READ后,可以直接改动IRP CURRENT STACK 中的FILE OBJECT,具体操作是:       1。MyIrpStack=IoGetCurrentIrpStackLocation(...)
           2. ItsFileObject=MyIrpStack->FileObject // 留着,万一要恢复你对IRP的修改
           3. MyNextIrpStack=IoGetNextIrpStackLocation(...)
           4. *NextIrpStack=*MyIrpStack;  // copy stack
              MyNextIrpStack->FileObject=MyNewFileObject;
              MyNextIrpStack->DeviceObject=MyNewDevice;
           5. IoCallDriver(MyNewDevice , pIrp);
其中,MYNEWFILEOBJECT可以使用ZWCREATEFILE来先打开该文件,并获得句柄,在用  什么 ...ObReferenceObjectByHandle(),来得到。
当然,这都是要点,不是程序,(不过很近似:))你再漫漫调,如果是NTFS 要注意:少碰元文件,少碰PAGEFILE。SYS以及敏感的系统文件
Supermi
驱动牛犊
驱动牛犊
  • 注册日期2001-10-20
  • 最后登录2014-06-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2002-04-25 15:27
另外,要是你不想用ZWCREATEFILE , 那就看看我在那贴上留的程序,可以有效的避免重入。
fkddn
驱动小牛
驱动小牛
  • 注册日期2002-03-28
  • 最后登录2005-11-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2002-04-25 15:48
我感觉也是重入的问题,也许我没有彻底完成这个irp包,致使它被不停的发过来,那么到底如何彻底完成它呢?
情赐教.
Supermi
驱动牛犊
驱动牛犊
  • 注册日期2001-10-20
  • 最后登录2014-06-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2002-04-26 00:33
下文引述我曾经的帖子,该程序将能通过自己构建IRP,并下传。而不象ZWCREATEFILE()会重新回到上层构件IRP然后再下传(这是引起重入的根源)。对了,其中 IO COMPLETION ROUNTINE 你就自己编一编吧,很容易,就是唤醒同步事件,然后返回STATUS_MORE_PROCESSING_REQUIED,这样防止IRP继续向上返回。
只要OPEN FILE的时候没有重入,以后你只是改动IRP,并继续下传,不会出现重入了。我成功的用于我的一些东东,效果优秀。
   怎么样?够义气了吧,以下一段代码可是精华,够给你的软件顶起半边天了:),其实,我本不想公开这些高中好不容易写的代码,但我总觉得,我们国家的高手都在窝里斗,没劲,所以我还是主张公开,旦愿大家都能这样!我也有很多问题,但大多数知道答案的人都不说,我也很生气,我想结识更多的高手交流,我的E MAIL:
li-gen@x263.net ,欢迎结识你们
-----------------------------------------------------------
   发表于: 2002/2/22 - 18:55
版主,你好像误解了那个人提出的问题.不光是要将IRP发送到特定的FSD栈里的某一层.而是要在我自己的Filter中Create 文件,而又不重入我的Filter。有一种好方法,就是自己建立IRP请求,然后下传。其中用到了一些构建自己的IRP,以及FileObject的方法。
下面是创建避免重入的关键代码,用该代码可以直接构建并下传打开文件的IRP。不过,这只是测试版的代码,如果哪位大侠发现这里的Bug,谢谢。另外感谢Smith, Joel 的指导。

NTSTATUS FsSimpleOpen(PUNICODE_STRING pstrName, ACCESS_MASK DesiredAccess, PDEVICE_OBJECT pVolume, PDEVICE_OBJECT pRealDevice, PFILE_OBJECT pParent, PFILE_OBJECT *ppFile)

{
PIRP pIrp = NULL;
PIO_STACK_LOCATION pStack;
KEVENT event;
IO_STATUS_BLOCK stat;
NTSTATUS ntRet;
PFILE_OBJECT pFile = NULL;
OBJECT_ATTRIBUTES oa;
ACCESS_STATE AccessState;
HANDLE hFile = NULL;
IO_SECURITY_CONTEXT ctx;
ULONG *pAuxData = ExAllocatePool(NonPagedPool, 1024);

if (pAuxData == NULL)
{
ntRet = STATUS_INSUFFICIENT_RESOURCES;
CLEANUP();
}

ASSERT(pVolume != NULL);
ASSERT(pRealDevice != NULL);
ASSERT(ppFile != NULL);
ASSERT(pstrName != NULL);

memset(pAuxData, 0, 1024);

//initialize an event and an IRP to send to the fsd
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
pIrp = IoAllocateIrp(pVolume->StackSize, FALSE);
IF_OUTOFMEMORY_CLEANUP(pIrp, &ntRet);

InitializeObjectAttributes(&oa,
NULL,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);

//create a file object for the irp
ntRet = ObCreateObject(KernelMode,
*IoFileObjectType,
&oa,
KernelMode,
0,
sizeof(FILE_OBJECT),
0,
0,
&pFile);

IF_FAIL_CLEANUP(ntRet);

//initialize the file object
RtlZeroMemory(pFile, sizeof(FILE_OBJECT));
pFile->Type = IO_TYPE_FILE;
pFile->Size = sizeof(FILE_OBJECT);
pFile->DeviceObject = pRealDevice;
pFile->Flags = FO_SYNCHRONOUS_IO;
pFile->RelatedFileObject = pParent;

//initialize embedded synch objects
KeInitializeEvent(&pFile->Lock, SynchronizationEvent, FALSE);
KeInitializeEvent(&pFile->Event, NotificationEvent, FALSE);

//copy the file name into the buffer
pFile->FileName.Buffer = ExAllocatePool(NonPagedPool, pstrName->MaximumLength);
if (pFile->FileName.Buffer == NULL)
{
ntRet = STATUS_INSUFFICIENT_RESOURCES;
CLEANUP();
}

pFile->FileName.MaximumLength = pstrName->MaximumLength;
pFile->FileName.Length = pstrName->Length;
RtlCopyMemory(pFile->FileName.Buffer, pstrName->Buffer, pstrName->Length);

//setup the irp
pIrp->UserEvent = &event;
pIrp->UserIosb = &stat;
pIrp->Tail.Overlay.Thread = KeGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFile;
pIrp->RequestorMode = KernelMode;
pIrp->Flags |= (IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API);
pIrp->MdlAddress = NULL;
pIrp->PendingReturned = FALSE;
pIrp->Cancel = FALSE;
pIrp->CancelRoutine = NULL;
pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;

//Set up the I/O stack location.
pStack = IoGetNextIrpStackLocation(pIrp);
pStack->MajorFunction = IRP_MJ_CREATE;
pStack->DeviceObject = pVolume;
pStack->FileObject = pFile;

//create an access state for the sd
ntRet = SeCreateAccessState(&AccessState, pAuxData, DesiredAccess, IoGetFileObjectGenericMapping());
IF_FAIL_CLEANUP(ntRet);

//fill out the create\'s security context
ctx.AccessState = &AccessState;
ctx.DesiredAccess = DesiredAccess;
ctx.SecurityQos = NULL;
ctx.FullCreateOptions = 0;

//fill out the the create parameter
pStack->Parameters.Create.SecurityContext = &ctx;
pStack->Parameters.Create.Options = FILE_OPEN << 24;
pStack->Parameters.Create.FileAttributes = FILE_ATTRIBUTE_NORMAL;
pStack->Parameters.Create.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
pStack->Parameters.Create.EaLength = 0;

//set the completion routine (that will free the irp)
IoSetCompletionRoutine(pIrp, FsDefaultComplete, 0, TRUE, TRUE, TRUE);

//Send it to the FSD
ntRet = IoCallDriver(pVolume, pIrp);
pIrp = NULL;

if (ntRet == STATUS_PENDING)
{
//wait for the io to complete
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
ntRet = stat.Status;
}

CLEANUP:

SAFE_FREE_POOL(pAuxData);

if (!NT_SUCCESS(ntRet))
{
if (pIrp != NULL)
{
IoFreeIrp(pIrp);
}
if (pFile)
{
SAFE_FREE_POOL(pFile->FileName.Buffer);
pFile->DeviceObject = NULL;
ObDereferenceObject(pFile);
}
}
else
{
FsReferenceDeviceAndVpb(pFile);

//set the out param
*ppFile = pFile;
}
return ntRet;
}

VOID FsReferenceDeviceAndVpb(PFILE_OBJECT pFile)
{
NTSTATUS ntRet;

ASSERT(pFile->Vpb != NULL ? pFile->DeviceObject->Vpb != NULL :
pFile->DeviceObject->Vpb == NULL);

//Increment RealDevice\'s reference count.
InterlockedIncrement(&pFile->DeviceObject->ReferenceCount);

//Increment Vpb\'s reference count, if one exists.
if (pFile->Vpb)
{
ASSERT((pFile->Vpb->Flags & VPB_MOUNTED) && !(pFile->Vpb->Flags & VPB_LOCKED));
InterlockedIncrement(&pFile->Vpb->ReferenceCount);
}
}


我可不想要钱。我还是学生嘛,但是么,我觉得有技术就因该提供。
希望 版主 多提意见。但是如果有哪位未经我同意,把本程序投稿到相管杂志或是本站的资料文章区,来骗取个人利益,我一定饶不了他。

-----------------------------------------------------------
 

____________________


 
游客

返回顶部