如何将本地(NT)path名转换为Win32path名?

我正在报告从本地系统API收集的一些信息。 (我知道这是不好的….但是我得到的信息是我无法得到的,而且在这个时候出现的时候我不得不更新我的应用程序。

本地API返回本地path名,如ob ,即\SystemRoot\System32\Ntoskrnl.exe\??\C:\Program Files\VMWare Workstation\vstor-ws60.sys

我可以replace常见的前缀,即

 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将会把它们转换成Win32path名,我会非常惊讶的。 这样的API是否存在?

我们在生产代码中这样做。 据我所知,没有处理这个问题的API(公共或私有)。 我们只是用一些前缀做一些字符串比较,它对我们很有用。

显然有一个名为RtlNtPathNameToDosPathName()在ntdll.dll(XP引入)的功能,但我不知道它是什么; 不过,我猜想它还有更多与\ Device \ Harddisk0之类的东西有关。

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

这是你可以尝试的东西。 首先使用NtCreateFile打开文件,音量等进行阅读。 然后使用返回的HANDLE来获取这里描述的完整路径。

检查这在Win32中获取规范路径名。 这可能对您有所帮助:

http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html

看到我对这个问题的回答 。

您需要首先获取该路径的文件句柄,然后获取句柄的Win32路径。

我写了一个函数,将不同类型的NT设备名称(文件名,COM端口,网络路径等)转换成DOS路径。

有两个功能。 一个把手柄转换成NT路径,另一个把这个NT路径转换成DOS路径。

看看这里: 如何获取与打开HANDLE关联的名称

 // "\Device\HarddiskVolume3" (Harddisk Drive) // "\Device\HarddiskVolume3\Temp" (Harddisk Directory) // "\Device\HarddiskVolume3\Temp\transparent.jpeg" (Harddisk File) // "\Device\Harddisk1\DP(1)0-0+6\foto.jpg" (USB stick) // "\Device\TrueCryptVolumeP\Data\Passwords.txt" (Truecrypt Volume) // "\Device\Floppy0\Autoexec.bat" (Floppy disk) // "\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB" (DVD drive) // "\Device\Serial1" (real COM port) // "\Device\USBSER000" (virtual COM port) // "\Device\Mup\ComputerName\C$\Boot.ini" (network drive share, Windows 7) // "\Device\LanmanRedirector\ComputerName\C$\Boot.ini" (network drive share, Windwos XP) // "\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" (network folder share, Windwos XP) // "\Device\Afd" (internet socket) // "\Device\Console000F" (unique name for any Console handle) // "\Device\NamedPipe\Pipename" (named pipe) // "\BaseNamedObjects\Objectname" (named mutex, named event, named semaphore) // "\REGISTRY\MACHINE\SOFTWARE\Classes\.txt" (HKEY_CLASSES_ROOT\.txt)