我正在报告从本机系统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"));
}
但如果没有一些API,本地或其他方式,将这些转换为Win32路径名,我会感到非常惊讶。是否存在这样的API?
7条答案
按热度按时间i2byvkas1#
我们在生产代码中这样做。据我所知,没有API(公共或私有)处理这个问题。我们只是用几个前缀做一些字符串比较,这对我们很有效。
显然,在ntdll.dll中有一个名为RtlNtPathNameToDosPathName()的函数(XP中引入的?),但我完全不知道它是做什么的;不过,我想这与\Device\Harddisk0之类的东西有更多的关系。
但我不确定是否真的需要这样的功能。Win32将路径(从NTFS文件等的意义上讲)传递给NT; NT不传递路径到Win32。所以ntdll.dll不需要从NT路径转到Win32路径。在某些NT查询函数返回完整路径的罕见情况下,任何转换函数都可以在Win32 dll内部(例如,不出口)。我甚至不知道他们是否会打扰,因为像GetModuleFileName()这样的东西只会返回用于加载图像的任何路径。我想这只是一个抽象的漏洞。
xurqigkl2#
你可以试试。首先使用NtCreateFile打开文件、卷等。用于阅读。然后使用返回的HANDLE获取完整路径,如here所述。
ds97pgxw3#
这是一个有点晚了,但我仍然会张贴我的答案,因为即使在今天这是一个非常好的问题!
我将分享我的一个功能测试和用于转换NT到DOS路径。在我的情况下,我还必须从ANSI转换到UNICODE,所以这是一个小奖励,让你看到和理解这是如何做到的。
所有这些代码都可以在用户模式下使用,所以我们需要先准备一些东西。
定义和结构:
功能:
辅助函数:
函数用法:
如前所述,在我的情况下,我需要从ANSI转换到UNICODE,这可能不适用于您的情况,因此您可以删除它。
如上所述,可用于创建自定义函数并根据需要转换路径。
izj3ouym4#
检查这个以获取Win32中的规范路径名。它可能对你有帮助:
http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html
rks48beu5#
请看我对这个问题的回答。
您需要首先获取该路径下文件的句柄,然后获取该句柄的Win32路径。
kpbwa7wx6#
我写了一个函数,将不同类型的NT设备名(文件名、COM端口、网络路径等)转换为DOS路径。
有两个功能。一个将句柄转换为NT路径,另一个将此NT路径转换为DOS路径。
看这里:如何获取与打开的HANDLE关联的名称
oo7oh9g97#
我在这条线上跑了一圈,因为我需要同样的东西。我使用了
EnumDeviceDrivers
和GetDeviceDriverFileName
函数,生成的文件名是NT格式的。然后我想对结果调用GetFileVersionInfo
,它不接受该路径格式。我第一次尝试使用未文档化的
RtlNtPathNameToDosPathName
函数,但它对我不起作用-路径有一个\\SystemRoot
前缀,said函数似乎对此没有任何作用。最终起作用的是https://stackoverflow.com/a/4452159/1451714中建议的NtCreateFile
方法。从句柄获取路径的一种更简单的方法是使用GetFinalPathNameByHandle,它从Windows Vista开始提供。下面是我的完整代码: