阅读:4785回复:12
IRP_MJ_READ中怎么得到盘符
我是sfilter
我几乎使用了所有方法得到盘符,IoVolumeDeviceToDosName. ObQueryNameString,sfgetfilename。 这些函数在IRP_MJ_READ例程中就是得不到,用就蓝屏。 但是这些方法在IRP_MJ_WRITE中都是可以使用的。 请告诉我一个方法。 谢谢 |
|
沙发#
发布于:2005-06-04 14:27
我也遇到过这种问题,你还是放弃在IRP_MJ_READ中读盘符的希望吧
|
|
板凳#
发布于:2005-06-06 10:42
FILEMON可以,
我去研究一下。看它是怎么得到的。 |
|
地板#
发布于:2005-06-06 12:48
看一下这里的讨论
http://www.driverdevelop.com/forum/html_81880.html?1118033250 |
|
地下室#
发布于:2005-06-06 15:41
楼上的,你开玩笑啊??
那个帖里面有我好几个回复呢。。。。 |
|
5楼#
发布于:2005-06-07 16:03
那就再仔细看看咯
|
|
6楼#
发布于:2005-06-07 18:10
looluo大侠!您已经说过两次,我们学习心切!请您具体指点一二!谢谢!
另外,我向您请教在那个帖子里我提出的问题: 请专家进来帮助分析我用windbg命令的输出的部分显示: Use !analyze -v to get detailed debugging information. BugCheck C2, {7, cd4, 81bca330, f888e2ac} Probably caused by : Sfilter.sys ( Sfilter!SfCreate+11e ) 这里的SfCreate+11e是加16进制的语句吗? BAD_POOL_CALLER (c2) The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc. 在Sfilter.c里应该如何设置IRQL level?这里的或者double freeing the same allocation, etc.是否是我们使用的ExFreePool与函数RtlVolumeDeviceToDosName或IoVolumeDeviceToDosName里的释放内存池2次了? Arguments: Arg1: 00000007, Attempt to free pool which was already freed而我们不使用ExFreePool,照样,是假死机!请指教? Arg2: 00000cd4, (reserved) Arg3: 81bca330, Memory contents of the pool block Arg4: f888e2ac, Address of the block of pool being deallocated 再次谢谢专家能进来的热心帮助!谢谢! |
|
|
7楼#
发布于:2005-06-09 11:46
我恢复一下上面两位
我测试的机器是Windows XP sp2 1.IoVolumeDeviceToDosName(RtlVolumeDeviceToDosName)在IRP_MJ_CREATE中使用是没有问题的,下面是我写在SfDisplayCreateFileName中代码,没有问题 UNICODE_STRING dosname; IoVolumeDeviceToDosName(irpSp->FileObject->DeviceObject, &dosname); SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES, (\"SFilter!SfDisplayCreateVolumeName: Opened %wZ\\n\", &dosname) ); ExFreePool(dosname.Buffer); 2.IoVolumeDeviceToDosName(RtlVolumeDeviceToDosName)在IRP_MJ_READ中的确有问题,我看了源码后发现问题出在IoVolumeDeviceToDosName构造IRP去查询DeviceName,如果把这部分去掉就没有问题,下面是我修改的RtlVolumeDeviceToDosName,参数部分有改变,第一个参数是传进去的设备名称,这个名称怎么取下面讲 NTSTATUS QuerySymbolicLink( IN PUNICODE_STRING SymbolicLinkName, OUT PUNICODE_STRING LinkTarget ) /*++ Routine Description: This routine returns the target of the symbolic link name. Arguments: SymbolicLinkName - Supplies the symbolic link name. LinkTarget - Returns the link target. Return Value: NTSTATUS --*/ { OBJECT_ATTRIBUTES oa; NTSTATUS status; HANDLE h; InitializeObjectAttributes(&oa, SymbolicLinkName, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &oa); if (!NT_SUCCESS(status)) { return status; } LinkTarget->MaximumLength = 200*sizeof(WCHAR); LinkTarget->Length = 0; LinkTarget->Buffer = ExAllocatePool(PagedPool, LinkTarget->MaximumLength); if (!LinkTarget->Buffer) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength); status = ZwQuerySymbolicLinkObject(h, LinkTarget, NULL); ZwClose(h); if (!NT_SUCCESS(status)) { ExFreePool(LinkTarget->Buffer); } return status; } NTSTATUS SFRtlVolumeDeviceToDosName( IN PUNICODE_STRING DeviceName, OUT PUNICODE_STRING DosName ) /*++ Routine Description: This routine returns a valid DOS path for the given device object. This caller of this routine must call ExFreePool on DosName->Buffer when it is no longer needed. Arguments: VolumeDeviceObject - Supplies the volume device object. DosName - Returns the DOS name for the volume Return Value: NTSTATUS --*/ { NTSTATUS status; UNICODE_STRING driveLetterName; WCHAR c; UNICODE_STRING linkTarget; RtlInitUnicodeString(&driveLetterName, L\"\\\\??\\\\C:\"); for (c = \'A\'; c <= \'Z\'; c++) { driveLetterName.Buffer[4] = c; status = QuerySymbolicLink(&driveLetterName, &linkTarget); if (!NT_SUCCESS(status)) { continue; } if (RtlEqualUnicodeString(&linkTarget, DeviceName, TRUE)) { ExFreePool(linkTarget.Buffer); break; } ExFreePool(linkTarget.Buffer); } if (c <= \'Z\') { DosName->Buffer = ExAllocatePool(PagedPool, 3*sizeof(WCHAR)); if (!DosName->Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } DosName->MaximumLength = 6; DosName->Length = 4; DosName->Buffer[0] = c; DosName->Buffer[1] = \':\'; DosName->Buffer[2] = 0; return STATUS_SUCCESS; } /*for (c = \'A\'; c <= \'Z\'; c++) { driveLetterName.Buffer[4] = c; InitializeListHead(&devicesInPath); status = FindPathForDevice(&driveLetterName, &deviceName, &devicesInPath, DosName); if (NT_SUCCESS(status)) { DosName->Length -= 4*sizeof(WCHAR); RtlMoveMemory(DosName->Buffer, &DosName->Buffer[4], DosName->Length); DosName->Buffer[DosName->Length/sizeof(WCHAR)] = 0; return status; } }*/ return status; } 最后注掉的部分是为了简化处理,这部分处理在24个盘符中找不到的情况,我没有仔细研究。 3.怎么在IRP_MJ_READ中取盘符。其实这个盘符对应的设备名一直在DeviceExtension中,可以在Create的时候就将盘符取出,保存在DeviceExtension中,Filemon就是这么做的,但是他取盘符不是用的RtlVolumeDeviceToDosName,但是原理是一样的,在Read中取盘符可以使用上面的函数。 4.为什么不能在IRP_MJ_READ中用sfgetfilename。sfgetfilename在内部使用的是ObQueryNameString,但是在IRP_MJ_READ中使用这个函数有IRP重入的问题,所以不能使用这个函数。在这里取文件名可以是使用Filespy中的方法,也可以使用Filemon的,两者是差不多,但是我在试Filemon老是有点问题,索性就没去研究。下面是我从filespy中抽取的方法,注意这里是Filespy中取文件名case 5CASE 5: We are retrieving the file name sometime after the CREATE operation. VOID SFGetFullPath( PFILE_OBJECT fileObject, PSFILTER_DEVICE_EXTENSION devExt, PUNICODE_STRING FileName ) { PFILE_NAME_INFORMATION fileNameInfo; ULONG returnLength; UCHAR buffer[sizeof(FILE_NAME_INFORMATION) + MAXPATHLEN]; fileNameInfo = (PFILE_NAME_INFORMATION)buffer; if( fileNameInfo) { SpyQueryFileSystemForFileName( fileObject, devExt->AttachedToDeviceObject, sizeof( buffer ), fileNameInfo, &returnLength ); RtlCopyMemory(FileName->Buffer, fileNameInfo->FileName, fileNameInfo->FileNameLength ); ); } } 这里取到的文件名加上前面取的盘符就可以得到完整的文件路径名。 [编辑 - 6/9/05 by looluo] |
|
8楼#
发布于:2005-06-13 16:30
looluo,您好!
谢谢您的无私真诚地帮助!我没法在这个帖子给您放分,以后弥补! 1 您的的文章里的SpyQueryFileSystemForFileName函数的原代码在那里能找到? 我已经查到了! 2 我今天开始看您给出的代码: 1)我比较您的QuerySymbolicLink函数与windows 2k原代码dev2dos.c里这个函数相比,您多出一条:RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength); 您修改了原来的系统函数啊,相应的您是怎么做的? 2)您将RtlVolumeDeviceToDosName函数自己重新构造,改名为 SFRtlVolumeDeviceToDosName;是这样的吧? 您将RtlVolumeDeviceToDosName的最后/*for (c = \'A\'; c <= \'Z\'; c++) { 段删去,按您说法,不删也可以! 3)您自己编写了SFGetFullPath函数吧?浪费您的时间了。抱歉! 希望得到您的帮助!谢谢! lgh@mobileelife.com [编辑 - 6/13/05 by lgh41] [编辑 - 6/15/05 by lgh41] [编辑 - 6/15/05 by lgh41] |
|
|
9楼#
发布于:2005-06-28 11:00
对了,我也发现IRP_MJ_READ和IRP_MJ_WRITE有很大的区别。
本来还以为它们很多方面应该是类似的。 |
|
|
10楼#
发布于:2005-06-28 11:37
我在IRP_MJ_CREATE中用RtlVolumeDeviceToDosName()得到盘符,然后在IRP_MJ_READ中得到路径,最后将它们连接起来
|
|
11楼#
发布于:2005-07-05 10:53
looluo:谢谢您的慷慨!
我是新手,笨手!您写出的内容我基本理解;但我一直困惑您的RtlVolumeDeviceToDosName,第一个参数是传进去的设备名称,这个设备名称您在文章里没有给出! 您反对用ObQueryNameString函数得到设备名,为了避免这个函数的重入造成死机;您又不使用RtlvolumeDeviceTODosName函数的源代码的开始寻找设备名的方法;那您如何找设备名? 要应用您的成果,我们调用RtlVolumeDeviceToDosName函数的第一个实际参数是传进去的设备名称的参数;更何况您在您的程序里调用if (RtlEqualUnicodeString(&linkTarget, DeviceName, TRUE)) { 也要求这个设备名称啊! 请你给点提示,指点指点好吗! 请回复给:lgh@mobileelife.com 您回复后,我可以将我的代码发给您! 引用:“2.IoVolumeDeviceToDosName(RtlVolumeDeviceToDosName)在IRP_MJ_READ中的确有问题,我看了源码后发现问题出在IoVolumeDeviceToDosName构造IRP去查询DeviceName,如果把这部分去掉就没有问题,下面是我修改的RtlVolumeDeviceToDosName,参数部分有改变,第一个参数是传进去的设备名称,这个名称怎么取下面讲 ” |
|
|
12楼#
发布于:2008-04-17 00:52
非常感谢looluo的无私奉献!
|
|