zhjie374
驱动小牛
驱动小牛
  • 注册日期2004-10-27
  • 最后登录2012-01-17
  • 粉丝2
  • 关注1
  • 积分17分
  • 威望144点
  • 贡献值1点
  • 好评度21点
  • 原创分0分
  • 专家分0分
阅读:4785回复:12

IRP_MJ_READ中怎么得到盘符

楼主#
更多 发布于:2005-06-03 17:53
我是sfilter
我几乎使用了所有方法得到盘符,IoVolumeDeviceToDosName.
ObQueryNameString,sfgetfilename。
这些函数在IRP_MJ_READ例程中就是得不到,用就蓝屏。

但是这些方法在IRP_MJ_WRITE中都是可以使用的。

请告诉我一个方法。

谢谢

最新喜欢:

rhpengrhpeng linshierlinshi...
xuAmigo
驱动小牛
驱动小牛
  • 注册日期2004-11-11
  • 最后登录2006-01-12
  • 粉丝0
  • 关注0
  • 积分58分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-06-04 14:27
我也遇到过这种问题,你还是放弃在IRP_MJ_READ中读盘符的希望吧
zhjie374
驱动小牛
驱动小牛
  • 注册日期2004-10-27
  • 最后登录2012-01-17
  • 粉丝2
  • 关注1
  • 积分17分
  • 威望144点
  • 贡献值1点
  • 好评度21点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-06-06 10:42
FILEMON可以,
我去研究一下。看它是怎么得到的。
looluo
驱动牛犊
驱动牛犊
  • 注册日期2001-09-15
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2005-06-06 12:48
看一下这里的讨论
http://www.driverdevelop.com/forum/html_81880.html?1118033250
zhjie374
驱动小牛
驱动小牛
  • 注册日期2004-10-27
  • 最后登录2012-01-17
  • 粉丝2
  • 关注1
  • 积分17分
  • 威望144点
  • 贡献值1点
  • 好评度21点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-06-06 15:41
楼上的,你开玩笑啊??

那个帖里面有我好几个回复呢。。。。
looluo
驱动牛犊
驱动牛犊
  • 注册日期2001-09-15
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2005-06-07 16:03
那就再仔细看看咯
lgh41
驱动小牛
驱动小牛
  • 注册日期2004-12-14
  • 最后登录2006-09-24
  • 粉丝0
  • 关注0
  • 积分203分
  • 威望28点
  • 贡献值0点
  • 好评度14点
  • 原创分0分
  • 专家分0分
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

再次谢谢专家能进来的热心帮助!谢谢!
lgh41
looluo
驱动牛犊
驱动牛犊
  • 注册日期2001-09-15
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
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]
lgh41
驱动小牛
驱动小牛
  • 注册日期2004-12-14
  • 最后登录2006-09-24
  • 粉丝0
  • 关注0
  • 积分203分
  • 威望28点
  • 贡献值0点
  • 好评度14点
  • 原创分0分
  • 专家分0分
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]
lgh41
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-06-28 11:00
对了,我也发现IRP_MJ_READ和IRP_MJ_WRITE有很大的区别。
本来还以为它们很多方面应该是类似的。
[b]万水千山总是情,回个帖子行不行?[/b]
xuAmigo
驱动小牛
驱动小牛
  • 注册日期2004-11-11
  • 最后登录2006-01-12
  • 粉丝0
  • 关注0
  • 积分58分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2005-06-28 11:37
我在IRP_MJ_CREATE中用RtlVolumeDeviceToDosName()得到盘符,然后在IRP_MJ_READ中得到路径,最后将它们连接起来
lgh41
驱动小牛
驱动小牛
  • 注册日期2004-12-14
  • 最后登录2006-09-24
  • 粉丝0
  • 关注0
  • 积分203分
  • 威望28点
  • 贡献值0点
  • 好评度14点
  • 原创分0分
  • 专家分0分
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,参数部分有改变,第一个参数是传进去的设备名称,这个名称怎么取下面讲 ”
lgh41
Gmxpsoft
驱动牛犊
驱动牛犊
  • 注册日期2007-09-20
  • 最后登录2011-10-11
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望61点
  • 贡献值1点
  • 好评度30点
  • 原创分1分
  • 专家分0分
12楼#
发布于:2008-04-17 00:52
非常感谢looluo的无私奉献!
游客

返回顶部