[C++][代码] Windows系统 文件Device路径转为Win32路径

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;
}

点赞

本文标签:

版权声明:本博客所有文章除特别声明外,本文皆为《shiver blog》原创,转载请保留文章出处。

本文链接:[C++][代码] Windows系统 文件Device路径转为Win32路径 - https://www.binary-monster.top/article/51

1

发表评论

电子邮件地址不会被公开。 必填项已用*标注