如何将本机(NT)路径名转换为Win32路径名?

Bil*_*eal 7 c++ windows nt native

我正在报告从本机系统API收集的一些信息.(我知道这很糟糕......但是我得到的信息是我无法得到的,而且如果/当这个时间到来时我不得不更新我的应用程序.)

本机API返回本地路径名,所看到的ob,即\SystemRoot\System32\Ntoskrnl.exe,或\??\C:\Program Files\VMWare Workstation\vstor-ws60.sys.

我可以替换常见的前缀,即

std::wstring NtPathToWin32Path( std::wstring ntPath )
{
    if (boost::starts_with(ntPath, L"\\\\?\\"))
    {
        ntPath.erase(ntPath.begin(), ntPath.begin() + 4);
        return ntPath;
    }
    if (boost::starts_with(ntPath, L"\\??\\"))
    {
        ntPath.erase(ntPath.begin(), ntPath.begin() + 4);
    }
    if (boost::starts_with(ntPath, L"\\"))
    {
        ntPath.erase(ntPath.begin(), ntPath.begin() + 1);
    }
    if (boost::istarts_with(ntPath, L"globalroot\\"))
    {
        ntPath.erase(ntPath.begin(), ntPath.begin() + 11);
    }
    if (boost::istarts_with(ntPath, L"systemroot"))
    {
        ntPath.replace(ntPath.begin(), ntPath.begin() + 10, GetWindowsPath());
    }
    if (boost::istarts_with(ntPath, L"windows"))
    {
        ntPath.replace(ntPath.begin(), ntPath.begin() + 7, GetWindowsPath());
    }
    return ntPath;
}

TEST(Win32Path, NtPathDoubleQuestions)
{
    ASSERT_EQ(L"C:\\Example", NtPathToWin32Path(L"\\??\\C:\\Example"));
}

TEST(Win32Path, NtPathUncBegin)
{
    ASSERT_EQ(L"C:\\Example", NtPathToWin32Path(L"\\\\?\\C:\\Example"));
}

TEST(Win32Path, NtPathWindowsStart)
{
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\Windows\\Hello\\World"));
}

TEST(Win32Path, NtPathSystemrootStart)
{
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\SystemRoot\\Hello\\World"));
}

TEST(Win32Path, NtPathGlobalRootSystemRoot)
{
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\globalroot\\SystemRoot\\Hello\\World"));
}
Run Code Online (Sandbox Code Playgroud)

但如果没有一些原生或其他的API会将这些API转换为Win32路径名,我会非常惊讶.这样的API是否存在?

Luk*_*uke 8

我们在生产代码中执行此操作.据我所知,没有API(公共或私人)处理这个问题.我们只是用一些前缀做一些字符串比较,它对我们有用.

显然在ntdll.dll中有一个名为RtlNtPathNameToDosPathName()的函数(在XP中引入?),但我不知道它做了什么; 我猜它有更多与像\ Device\Harddisk0这样的东西有关.

不过,我不确定是否真的需要这样的功能.Win32将路径(在CreateFile等意义上)传递给NT; NT不会将路径传递给Win32.所以ntdll.dll实际上并不需要从NT路径转到Win32路径.在极少数情况下,某些NT查询函数返回完整路径,任何转换函数都可能是Win32 dll的内部函数(例如,未导出).我甚至不知道他们是否打扰,因为像GetModuleFileName()这样的东西只会返回用于加载图像的任何路径.我想这只是一个漏洞的抽象.

  • 遗憾的是 Microsoft 没有为此提供文档化的 API。Windows内部整天把NT路径转换成DOS路径,但我们程序员却做不到。如果您对如何使用 RtlNtPathNameToDosPathName() 感兴趣,请查看此处:http://forum.sysinternals.com/rtlntpathnametodospathname_topic27697.html (2认同)

Pra*_*ian 5

这是你可以尝试的东西。首先使用NtCreateFile打开文件、卷等进行读取。然后使用返回的 HANDLE 获取此处所述的完整路径。