阅读:2538回复:19
很急:关于文件过滤的问题,请帮忙,60分相送
我在做一个文件过滤器,具体功能如下:
在硬盘的一个分区建立一个特定的目录,如 \"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包我得作怎样的处理? 请各位指点,越清楚越好。 |
|
沙发#
发布于:2002-04-12 11:29
我的开发环境是win 2000
过滤器是挂接在ntfs之上的 |
|
板凳#
发布于:2002-04-12 12:29
我在做一个文件过滤器,具体功能如下: 这样是不行的,因为你的文件\"E:\\test\\doc.txt\"和你欲重定向的文件dvd光驱\"g:\\doc.txt\"一般来说不是同一个文件系统,使用的驱动程序也不同,就此这一种情况来说,你的文件系统是NTFS,而重定向目标FSD则是CDFS或者DVDFS.这并不是一个一般的过滤驱动。 但一定是可以实现的,我的想法是这样: 拦截到你指定的目录的访问非常简单,你一定已经掌握了。至拦截到以后怎么重定向到另一个FSD,则首先你要得到你重定向的驱动程序创建的设备对象(完整的设备栈);你需要知道这个设备对象的议;然后你要完全重新构造IRP去请求这个服务,并设置完成例程等细节步骤。 这里不可避免地会调用ZwCreateFile()函数,这很可能会导至重入(IRP_MJ_CREATE),你需要小心地处理这个东西,本站有一篇文章专门探讨了这个问题。 以上是我的设想,但愿对你有帮助。 Best regards ! |
|
|
地板#
发布于:2002-04-12 13:48
谢谢Tom_lyd老兄先,我还想请教:
1.我的那个dvd 设备的文件系统是设置在ntfs之下的,我在重定向时,是否不必修改设备对象了(仍旧发往ntfs)? 2.这个重定向是否可以只在read例程里进行,而不是create例程? 3.那篇文章在哪里呢?怎么找不到? 急呀,明白的请帮忙…… |
|
地下室#
发布于:2002-04-12 14:54
谢谢Tom_lyd老兄先,我还想请教: 我认为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重入的问题。 |
|
|
5楼#
发布于:2002-04-13 15:05
首先恭喜Tom_lyd老兄。其次
依照你的指点,我又重新对我的过滤驱动理解了一下,它看来真的不是普通的过滤功能,得解决分层驱动的重入问题。可我以前从来没有自己分配过irp包,在解决重入时又遇到了几个疑问: (哎,没办法,老伴催的急,只好厚起脸皮问了,以后有时间一定好好研究) 1.我在我的read例程中构造了新的newirp,得到新目标设备,然后IoCallDriver(),在新设备创建我的文件,这个newirp包如何构造呢? 需要我的read例程得到的oldirp中的什么信息才能保证我在IoCompleteRoutine中利用这个newirp继续IoCallDriver(),调用新设备的read例程,将文件读到用户那里? 2.这样利用IoCompleteRoutine是否可行?我的那个oldirp该怎样处理? 先谢谢了,各位。 |
|
6楼#
发布于:2002-04-13 15:07
怎么搞的,为什么给不了分了?
|
|
7楼#
发布于:2002-04-20 16:09
现在我将irp重定向到了新的路径,并且在应用层读到了新设备下的文件。可是,我在关闭应用程序时就死机,softice提示:
break due to KebugCheckEx error=76 (PROCESS_HAS_LOCKED_PAGES) 我怀疑是那块内存没有释放,可总是找不到正确的地方 请遇到类似问题的大虾指点一下吧,谢谢了…… |
|
8楼#
发布于:2002-04-20 16:14
要养成在程序退出时释放驱动程序中申请的任何资源,多数是在Unload例程、IRP_MJ_CLOSE中做这些事情。但是有的驱动程序在和它挂接的应用程序关闭时,自身的Unload例程和IRP_MJ_CLOSE不一定能被执行到,可能是由程序自身的错误或者应用程序的某种特殊目的。然而IRP_MJ_CLEANUP却一定会被执行,因此,这里也是一个资源释放的好地方。
|
|
|
9楼#
发布于:2002-04-23 14:59
HI
我想你已经看过那篇讨论,我在那儿发表了一篇代码,你应该看到了吧,那代码可以避免你创建新的设备,也就是不用老外的办法, 我可以保证我的代码的可靠性,我想知道的是,你要做这种重定向干什么,可以告诉我吗?另外我想知道象你这样研究到文件驱动的人是在哪些单位工作,年龄层次呢?(因为我是大二,我想知道社会的需求,能告诉我吗?)你回答了,我可以给你一些技术提示,我可以告诉你怎样控制读写方向,怎样随心所欲的转换,而且不用调用ZWCREATEFILE,而且避免重入,不必构造irp也能干同样的事 。。。。 |
|
10楼#
发布于:2002-04-23 15:38
HI 哪篇讨论?哪篇文章? |
|
|
11楼#
发布于:2002-04-23 19:32
HI 你的条件倒是很特别嘛。 我的项目实际是为了利用在硬盘上的一个分区作缓冲,来管理多个dvd光驱。我希望能在读取只读文件时应用程序不去访问硬盘缓冲,而是直接去读dvd。大致的你明白了吧。 我研究这个东西纯粹是被老板逼的,来了活,就找个人干呗,我只对文件驱动有个大概的认识,从没做过。 我希望你能告诉我在控制读写方向时,需要注意些什么?我的程序可以转向了,可是在type一个txt文件时会不停的循环调用read例程去读文件的头512字节。这是为什么呢? 另外我想知道你为什么会研究起fsd呢? |
|
12楼#
发布于:2002-04-24 16:34
似乎有个简单的方法可以解决你的问题,与驱动无关,是在API这一层做。
用程序挂接CreateFile()函数,当CreatFile()的参数是你的磁盘目录下的文件,并且是只读时,就打开DVD上的相应文件,把HANDLE传回去。 |
|
|
13楼#
发布于:2002-04-24 16:57
似乎有个简单的方法可以解决你的问题,与驱动无关,是在API这一层做。 可是如何用程序挂接CreateFile()函数或是ReadFile()函数呢?是不是要做一个服务程序什么的? |
|
14楼#
发布于:2002-04-24 17:40
你要过滤的是具体的几个应用程序还是系统中的所有程序?如果是后者要稍微麻烦一点。
写一个DLL,插入进程的地址空间,修改模块的IMPORT DESCRIPTOR |
|
|
15楼#
发布于:2002-04-25 08:51
你要过滤的是具体的几个应用程序还是系统中的所有程序?如果是后者要稍微麻烦一点。 多谢你的指点,可我真的是个菜鸟,对你的提示不太明白。写个dll插入哪个进程的地址空间?怎么插?修改哪个模块的IMPORT DESCRIPTOR?怎么修改? |
|
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以及敏感的系统文件 |
|
17楼#
发布于:2002-04-25 15:27
另外,要是你不想用ZWCREATEFILE , 那就看看我在那贴上留的程序,可以有效的避免重入。
|
|
18楼#
发布于:2002-04-25 15:48
我感觉也是重入的问题,也许我没有彻底完成这个irp包,致使它被不停的发过来,那么到底如何彻底完成它呢?
情赐教. |
|
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); } } 我可不想要钱。我还是学生嘛,但是么,我觉得有技术就因该提供。 希望 版主 多提意见。但是如果有哪位未经我同意,把本程序投稿到相管杂志或是本站的资料文章区,来骗取个人利益,我一定饶不了他。 ----------------------------------------------------------- ____________________ |
|