Windows系统 文件Device路径转为Win32路径
将\Device\HarddiskVolume2\123.txt 转为 C:\123.txt
法1
BOOL DeviceDosPathToNtPath(const wchar_t* pszDosPath, wchar_t* pszNtPath)
{
static wchar_t szDriveStr[MAX_PATH] = { 0 };
static wchar_t szDevName[MAX_PATH] = { 0 };
wchar_t szDrive[3] = {0};
INT cchDevName;
INT i;
//检查参数
if (IsBadReadPtr(pszDosPath, 1) != 0)return FALSE;
if (IsBadWritePtr(pszNtPath, 1) != 0)return FALSE;
//获取本地磁盘字符串
ZeroMemory(szDriveStr, ARRAYSIZE(szDriveStr));
ZeroMemory(szDevName, ARRAYSIZE(szDevName));
if (GetLogicalDriveStringsW(sizeof(szDriveStr), szDriveStr))
{
for (i = 0; szDriveStr[i]; i += 4)
{
if (!wcscmp((const wchar_t*)&(szDriveStr[i]), L"A:") || !wcscmp((const wchar_t*)&(szDriveStr[i]), L"B:"))
continue;
szDrive[0] = szDriveStr[i];
szDrive[1] = szDriveStr[i + 1];
szDrive[2] = '\0';
if (!QueryDosDeviceW(szDrive, szDevName, MAX_PATH))//查询 Dos 设备名
return FALSE;
cchDevName = wcslen(szDevName);
int ret = wcsncmp(pszDosPath, (const wchar_t*)szDevName, cchDevName);
if (ret == 0)//命中
{
wcsncpy(pszNtPath, (const wchar_t*)szDrive, wcslen(szDrive));//复制驱动器
wcsncpy(pszNtPath + wcslen(szDrive), (const wchar_t*)pszDosPath + cchDevName, wcslen(pszDosPath + cchDevName));//复制路径
return TRUE;
}
}
}
wcsncpy(pszNtPath, pszDosPath, MAX_PATH);
return FALSE;
}
// \\Device\\HarddiskVolume2\\123.txt
// 为C:123.txt
int main() {
std::wstring nt_path = L"\\Device\\HarddiskVolume2\\123.txt";
wchar_t dosPath[1024] = { 0 };
DeviceDosPathToNtPath(nt_path.c_str(), dosPath);
return 0;
}
法2
#pragma once
#include <Windows.h>
#include <mutex>
#include <map>
#include <unordered_map>
#include <string>
#include <algorithm>
#include <string.h>
///
/// <summary>
/// 将windows驱动路径换成用户态路径,例如:
/// "\\Device\\HarddiskVolume3\\Windows\\System32\\notepad.exe" =>
/// "C:\\Windows\\System32\\notepad.exe"
/// </summary>
///
class TranslatePathFromDevie {
public:
inline static bool IsDevicePath(const std::wstring& device_path) {
if (device_path.size() < 8 || device_path[0] != L'\\') {
return false;
}
if (0 != wcsncmp(device_path.c_str(), LR"(\Device\)", 8)) {
return false;
}
return true;
}
///
/// <summary>
/// 枚举磁盘上所有的盘符与驱动路径对应关系
/// </summary>
/// <returns>小于0表示执行失败,大于0为枚举到的盘符数</returns>
///
int UpdateSystemDevice() {
int result = -1;
WCHAR VolumeName[MAX_PATH] = {0};
auto FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE) {
auto err = GetLastError();
printf("FindFirstVolumeW failed with error code %lu", err);
return -1;
}
m_map_translate_paths.clear();
BOOL success = TRUE;
for (; success != FALSE;
(success = FindNextVolumeW(FindHandle, VolumeName,
ARRAYSIZE(VolumeName)))) {
//
// Skip the \\?\ prefix and remove the trailing backslash.
auto index = wcslen(VolumeName) - 1;
if (VolumeName[0] != L'\\' || VolumeName[1] != L'\\' ||
VolumeName[2] != L'?' || VolumeName[3] != L'\\' ||
VolumeName[index] != L'\\') {
printf("FindNextVolumeW returned a bad path: %S\n",
VolumeName);
continue;
}
VolumeName[index] = L'\0';
WCHAR DeviceName[MAX_PATH] = {0};
auto CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName,
ARRAYSIZE(DeviceName));
if (CharCount == 0) {
auto err = GetLastError();
printf("QueryDosDeviceW failed with error code %lu", err);
continue;
}
_wcsupr_s(DeviceName);
VolumeName[index] = L'\\';
RetrieveVolumePaths(VolumeName, DeviceName);
}
result = static_cast<int>(m_map_translate_paths.size());
auto err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
printf("FindNextVolumeW failed with error code %lu", err);
if (result == 0) {
result = -2;
}
}
FindVolumeClose(FindHandle);
return result;
}
///
/// <summary>
/// 将驱动路径转换为用户态路径(就地修改返回引用)
/// </summary>
/// <param name="device_name">驱动路径字符串</param>
/// <returns></returns>
///
std::wstring& TranslateToPath(std::wstring& device_name) {
if (device_name.size() < 8 || device_name[0] != L'\\' ||
!IsDevicePath(device_name.c_str())) {
return device_name;
}
auto index = device_name.find('\\', 8);
std::wstring key(index == std::wstring::npos
? device_name
: device_name.substr(0, index));
if (key.empty()) {
return device_name;
}
std::transform(key.begin(), key.end(),
key.begin(), toupper);
//key = tt_to_upper(key);
if (m_map_translate_paths.size() == 0) {
UpdateSystemDevice();
}
for (auto i = 0;; i++) {
auto it = m_map_translate_paths.find(key);
if (it == m_map_translate_paths.end()) {
if (i == 0) {
UpdateSystemDevice();
continue;
}
break;
}
device_name = it->second + device_name.substr(index + 1);
break;
}
return device_name;
}
private:
bool RetrieveVolumePaths(__in LPCWSTR VolumeName, LPCWSTR DeviceName) {
DWORD CharCount = MAX_PATH + 1;
WCHAR Names[MAX_PATH + 1] = {0};
auto Success = GetVolumePathNamesForVolumeNameW(VolumeName, Names,
CharCount, &CharCount);
if (Success && Names[0] != NULL) {
m_map_translate_paths[DeviceName] = Names;
return true;
}
return false;
}
std::unordered_map<std::wstring, std::wstring> m_map_translate_paths;
};
void Test_TranslatePathFromDevie() {
TranslatePathFromDevie obj;
std::wstring tmp(
LR"(\Device\HarddiskVolume3\Windows\System32\notepad.exe)");
obj.TranslateToPath(tmp);
}
int main() {
TranslatePathFromDevie obj;
std::wstring tmp(
LR"(\Device\HarddiskVolume2\Windows\System32\notepad.exe)");
std::wstring ret = obj.TranslateToPath(tmp);
return 0;
}