阅读:1726回复:2
再提2000系统下irp_mj_read中获取盘符looluo 大虾请进
looluo大侠以前曾提过如何在irp_mj_read里面获取盘符内容如下:
我恢复一下上面两位 我测试的机器是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 ); ); } } 这里取到的文件名加上前面取的盘符就可以得到完整的文件路径名。 但是有两个问题我想问问looluo大侠 1 : SFRtlVolumeDeviceToDosName函数的第一个参数是怎样的?怎样获取? 2: 能否给出一段实际运用的例呢?就象第一个例子样。 谢谢:) |
|
沙发#
发布于:2007-07-26 11:13
ding!!!
|
|
板凳#
发布于:2007-07-26 15:16
Re:再提2000系统下irp_mj_read中获取盘符
各位大侠都帮下忙哈 |
|