紫水晶编程技术论坛 - 努力打造成全国最好的编程论坛

 找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 6739|回复: 4

[开源]NT路径转DOS路径的简单办法

[复制链接]

3

主题

78

帖子

0

精华

初来乍到

Rank: 1

积分
440
发表于 2018-1-19 11:04:10 | 显示全部楼层 |阅读模式
        以前也曾为NT路径转DOS路径而烦恼,网上翻了很久,总觉得那些操作太过繁琐,我本人比较懒,就一直想找个简单的办法,现在终于找到了。
        ring3下的NT路径转DOS路径,通常所采用的套路是查询符号链接,ring0下就好搞了,有IoVolumeDeviceToDosName ,IoQueryFileDosDeviceName 。看某位大表哥的博客,IoQueryFileDosDeviceName 接口在某个情况下会导致系统卡死。
        现在在提供一种办法,简单又粗暴,改改可以放到ring0下跑,粗略测试还是很靠谱的。套路如下:
  1. typedef struct _MOUNTDEV_NAME {
  2.         USHORT  NameLength;
  3.         WCHAR   Name[1];
  4. } MOUNTDEV_NAME, *PMOUNTDEV_NAME;

  5. typedef struct _MOUNTMGR_VOLUME_PATHS {
  6.         ULONG MultiSzLength;
  7.         WCHAR MultiSz[1];
  8. } MOUNTMGR_VOLUME_PATHS, *PMOUNTMGR_VOLUME_PATHS;

  9. #define MOUNTMGRCONTROLTYPE ((ULONG) 'm')
  10. #define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH \
  11.         CTL_CODE(MOUNTMGRCONTROLTYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)


  12. DWORD VolumeDeviceNameToDosName( IN LPCWSTR DeviceName, OUT LPWSTR DosName )
  13. {
  14.         PMOUNTDEV_NAME MountName = NULL;
  15.         CHAR buffer1[512] = { 0 };
  16.         CHAR buffer2[512] = { 0 };
  17.         HANDLE MountPointMgr = NULL;
  18.         DWORD BytesReturned = 0;

  19.         MountPointMgr = CreateFile(
  20.                                                 L"\\\\.\\MountPointManager",
  21.                                                 0,
  22.                                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  23.                                                 NULL,
  24.                                                 OPEN_EXISTING,
  25.                                                 0,
  26.                                                 NULL
  27.                                                 );
  28.         if( MountPointMgr == INVALID_HANDLE_VALUE )
  29.                 return GetLastError();

  30.         MountName = ( PMOUNTDEV_NAME )buffer1;
  31.         wcscpy( MountName->Name, DeviceName );
  32.         MountName->NameLength = wcslen( MountName->Name ) * 2;

  33.         DeviceIoControl(
  34.                                         MountPointMgr,
  35.                                         IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
  36.                                         MountName,
  37.                                         512,
  38.                                         buffer2,
  39.                                         512,
  40.                                         &BytesReturned,
  41.                                         NULL
  42.                                         );
  43.         if( ! GetLastError() )
  44.                 wcscpy( DosName, ( ( PMOUNTMGR_VOLUME_PATHS )buffer2 )->MultiSz );

  45.         CloseHandle( MountPointMgr );
  46.         return GetLastError();
  47. }
复制代码
输入:\Device\HarddiskVolume1
输出:C:

评分

参与人数 1水晶币 +60 收起 理由
Tesla.Angela + 60 赞一个!

查看全部评分

854

主题

3481

帖子

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

Rank: 125Rank: 125Rank: 125Rank: 125Rank: 125

积分
36100
发表于 2018-1-19 14:29:49 | 显示全部楼层
直接用QueryDosDevice可以兼容R3和R0:http://www.m5home.com/bbs/thread-7622-1-1.html

PS:杭州潜水艇(hzqst),出来走两步。

2

主题

31

帖子

1

精华

金牌会员

Rank: 4Rank: 4Rank: 4Rank: 4

积分
1244
发表于 2018-1-19 19:52:10 | 显示全部楼层
其实这个就是IoVolumeDeviceToDosName 的R3版本

7

主题

74

帖子

2

精华

钻石会员

Rank: 6Rank: 6

积分
2565
发表于 2018-1-19 23:33:36 | 显示全部楼层
//发个r0的
PWSTR _GetSymbolicTarget(PCWSTR pwSymbolic)
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING uSymbolic;
    NTSTATUS status;
    HANDLE hSymbolic;
    UNICODE_STRING uTarget;
    ULONG len = 0;
    WCHAR buf[4];
    PWSTR pwTarget;
   
    RtlInitUnicodeString(&uSymbolic, pwSymbolic);
    InitializeObjectAttributes(&oa, &uSymbolic, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL,NULL);
   
    status = ZwOpenSymbolicLinkObject(&hSymbolic, GENERIC_READ, &oa);
    if (!NT_SUCCESS(status))
    {
        DbgPrint(("hpsafe:%-4d [ERRO] ZwOpenSymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
        return NULL;
    }
   
    RtlInitEmptyUnicodeString(&uTarget, buf, 0);
    status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
    if (status != STATUS_BUFFER_TOO_SMALL)
    {
        DbgPrint(("hpsafe:%-4d [ERRO] ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
        return NULL;
    }

    pwTarget = ExAllocatePoolWithTag(NonPagedPool, len + sizeof(WCHAR), '_EL_');
    if (!pwTarget)
    {
        DbgPrint(("hpsafe:%-4d [ERRO] ExAllocatePoolWithTag failed.\n", __LINE__));
        ZwClose(hSymbolic);
        return NULL;
    }
   
    RtlInitEmptyUnicodeString(&uTarget, pwTarget, (USHORT)len + sizeof(WCHAR));
    status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
    ZwClose(hSymbolic);
   
    if (!NT_SUCCESS(status))
    {
        DbgPrint(("hpsafe:%-4d [ERRO] ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
        ExFreePoolWithTag(pwTarget, '_EL_');
        return NULL;
    }
   
    return pwTarget;
}

PWSTR _DosPathToNtPath(PCWSTR pwDosPath)
{
    PWSTR pwTarget, pNtPath;
    SIZE_T l1, l2;
    WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
   
    if ((*pwDosPath >= L'a' && *pwDosPath <= L'z' ||
        *pwDosPath >= L'A' && *pwDosPath <= L'Z') &&
        pwDosPath[1] == L':' && pwDosPath[2] == L'\\')
    {
        /* get nt drive path */
        pwDosDrive[12] = pwDosPath[0];
        pwTarget = _GetSymbolicTarget(pwDosDrive);
        if (!pwTarget)
            return NULL;

        /* concat two part */
        RtlStringCbLengthW(pwTarget, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l1);
        RtlStringCbLengthW(pwDosPath + 2, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l2);
        pNtPath = ExAllocatePoolWithTag(NonPagedPool, l1 + l2 + sizeof(WCHAR), '_EL_');
        if (pNtPath)
        {
            RtlStringCbCopyW(pNtPath, l1 + sizeof(WCHAR), pwTarget);
            RtlStringCbCopyW(pNtPath + l1 / sizeof(WCHAR), l2 + sizeof(WCHAR), pwDosPath + 2);
        }
        else
        {
            DbgPrint(("hpsafe:%-4d [ERRO] ExAllocatePoolWithTag failed.\n", __LINE__));
        }
        ExFreePoolWithTag(pwTarget, '_EL_');
        return pNtPath;
    }
    else
    {
        DbgPrint(("hpsafe:%-4d [ERRO] unsupported path: %ws.\n", __LINE__, pwDosPath));
        return NULL;
    }
}

PWSTR _NtPathToDosPath(PCWSTR pwNtPath)
{
    PWSTR pwDosPath;
    WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
    PWSTR pwTarget;
    WCHAR c;
    USHORT len;
    UNICODE_STRING usTarget;
    UNICODE_STRING usNtPath;
    UNICODE_STRING usDosPath;

    RtlInitUnicodeString(&usNtPath, pwNtPath);
    for (c = L'A'; c <= L'Z'; ++ c)
    {
        pwDosDrive[12] = c;
        pwTarget = _GetSymbolicTarget(pwDosDrive);
        if (!pwTarget)
            continue;
        /*
        DbgPrint(("hpsafe:%-4d [INFO] %c:\\ -> %ws.\n", __LINE__,
            (CHAR)c, pwTarget));
        */
        RtlInitUnicodeString(&usTarget, pwTarget);
        if (RtlPrefixUnicodeString(&usTarget, &usNtPath, TRUE))
        {
            len = (wcslen(pwNtPath) - wcslen(pwTarget) + 4) * sizeof(WCHAR);
            pwDosPath = ExAllocatePoolWithTag(NonPagedPool, len, '_EL_');
            if (!pwDosPath)
            {
                DbgPrint(("hpsafe:%-4d [ERRO] ExAllocatePoolWithTag failed.\n", __LINE__));
                return NULL;
            }
                        memset(pwDosPath, 0, len);
            RtlInitEmptyUnicodeString(&usDosPath, pwDosPath, len);
            RtlUnicodeStringCopyString(&usDosPath, L"x:");
            *pwDosPath = c;
            RtlUnicodeStringCatString(&usDosPath, pwNtPath + wcslen(pwTarget) );
            return pwDosPath;
        }
    }

    return NULL;
}

0

主题

108

帖子

0

精华

铜牌会员

Rank: 2Rank: 2

积分
87
发表于 2018-1-23 02:14:15 | 显示全部楼层
感谢分享,看看怎么实现的
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

手机版|Archiver|紫水晶工作室 ( 粤ICP备05020336号 )

GMT+8, 2024-4-24 14:19 , Processed in 0.026964 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表