将 Windows 设备路径解析为驱动器盘符

发布于 2024-07-07 03:50:08 字数 169 浏览 7 评论 0原文

如何将 NT 样式设备路径(例如 \Device\CdRom0)解析为其逻辑驱动器号(例如 G:\)?

编辑:卷名称与设备路径不同,因此不幸的是 GetVolumePathNamesForVolumeName() 将不起作用。

How do you resolve an NT style device path, e.g. \Device\CdRom0, to its logical drive letter, e.g. G:\ ?

Edit: A Volume Name isn't the same as a Device Path so unfortunately GetVolumePathNamesForVolumeName() won't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

滿滿的愛 2024-07-14 03:50:09

希望下面的代码足以解决这个问题 - 在初始化它之后,您只需要迭代集合即可找到匹配项。 您可能希望在插入集合之前将所有内容转换为大写/小写,以帮助提高查找性能。

typedef basic_string<TCHAR> tstring;
typedef map<tstring, tstring> HardDiskCollection;

void Initialise( HardDiskCollection &_hardDiskCollection )
{
    TCHAR tszLinkName[MAX_PATH] = { 0 };
    TCHAR tszDevName[MAX_PATH] = { 0 };
    TCHAR tcDrive = 0;

    _tcscpy_s( tszLinkName, MAX_PATH, _T("a:") );
    for ( tcDrive = _T('a'); tcDrive < _T('z'); ++tcDrive )
    {
        tszLinkName[0] = tcDrive;
        if ( QueryDosDevice( tszLinkName, tszDevName, MAX_PATH ) )
        {
            _hardDiskCollection.insert( pair<tstring, tstring>( tszLinkName, tszDevName ) );
        }
    }
}

Hopefully the following piece of code will give you enough to solve this - after you've initialised it, you just need to iterate through the collection to find your match. You may want to convert everything to upper/lower case before you insert into the collection to help with lookup performance.

typedef basic_string<TCHAR> tstring;
typedef map<tstring, tstring> HardDiskCollection;

void Initialise( HardDiskCollection &_hardDiskCollection )
{
    TCHAR tszLinkName[MAX_PATH] = { 0 };
    TCHAR tszDevName[MAX_PATH] = { 0 };
    TCHAR tcDrive = 0;

    _tcscpy_s( tszLinkName, MAX_PATH, _T("a:") );
    for ( tcDrive = _T('a'); tcDrive < _T('z'); ++tcDrive )
    {
        tszLinkName[0] = tcDrive;
        if ( QueryDosDevice( tszLinkName, tszDevName, MAX_PATH ) )
        {
            _hardDiskCollection.insert( pair<tstring, tstring>( tszLinkName, tszDevName ) );
        }
    }
}
半夏半凉 2024-07-14 03:50:09

也许您可以使用 GetVolumeNameForMountPoint 并迭代所有挂载点 A:\ 到 Z:\,在找到匹配项时中断?

http://msdn.microsoft.com/en-us /library/aa364994(VS.85).aspx

(我没有尝试过)

Maybe you could use GetVolumeNameForMountPoint and iterate through all mount points A:\ through Z:\, breaking when you find a match?

http://msdn.microsoft.com/en-us/library/aa364994(VS.85).aspx

(I haven't tried this)

避讳 2024-07-14 03:50:09

以下函数仅使用 C 完成这项工作

BOOL GetWin32FileName(const TCHAR* pszNativeFileName, TCHAR *pszWin32FileName)
{
    BOOL bFound = FALSE;

    // Translate path with device name to drive letters.
    TCHAR szTemp[MAX_PATH];
    szTemp[0] = '\0';

    if (GetLogicalDriveStrings(MAX_PATH - 1, szTemp))
    {
        TCHAR szName[MAX_PATH];
        TCHAR szDrive[3] = TEXT(" :");
        TCHAR* p = szTemp;

        do
        {
            // Copy the drive letter to the template string
            *szDrive = *p;

            // Look up each device name
            if (QueryDosDevice(szDrive, szName, MAX_PATH))
            {
                size_t uNameLen = _tcslen(szName);

                if (uNameLen < MAX_PATH)
                {
                    bFound = _tcsnicmp(pszNativeFileName, szName, uNameLen) == 0
                        && *(pszNativeFileName + uNameLen) == _T('\\');

                    if (bFound)
                    {
                        // Replace device path with DOS path
                        StringCchPrintf(pszWin32FileName,
                            MAX_PATH,
                            TEXT("%s%s"),
                            szDrive,
                            pszNativeFileName + uNameLen);
                    }
                }
            }
            // Go to the next NULL character.
            while (*p++);
        } while (!bFound && *p);
    }

    return(bFound);
}

Following function does the job using C only

BOOL GetWin32FileName(const TCHAR* pszNativeFileName, TCHAR *pszWin32FileName)
{
    BOOL bFound = FALSE;

    // Translate path with device name to drive letters.
    TCHAR szTemp[MAX_PATH];
    szTemp[0] = '\0';

    if (GetLogicalDriveStrings(MAX_PATH - 1, szTemp))
    {
        TCHAR szName[MAX_PATH];
        TCHAR szDrive[3] = TEXT(" :");
        TCHAR* p = szTemp;

        do
        {
            // Copy the drive letter to the template string
            *szDrive = *p;

            // Look up each device name
            if (QueryDosDevice(szDrive, szName, MAX_PATH))
            {
                size_t uNameLen = _tcslen(szName);

                if (uNameLen < MAX_PATH)
                {
                    bFound = _tcsnicmp(pszNativeFileName, szName, uNameLen) == 0
                        && *(pszNativeFileName + uNameLen) == _T('\\');

                    if (bFound)
                    {
                        // Replace device path with DOS path
                        StringCchPrintf(pszWin32FileName,
                            MAX_PATH,
                            TEXT("%s%s"),
                            szDrive,
                            pszNativeFileName + uNameLen);
                    }
                }
            }
            // Go to the next NULL character.
            while (*p++);
        } while (!bFound && *p);
    }

    return(bFound);
}
笑脸一如从前 2024-07-14 03:50:09

您可以查找所有卷的名称以匹配设备名称并获取驱动器号。这是一个示例:

int DeviceNameToVolumePathName(WCHAR *filepath) {
    WCHAR fileDevName[MAX_PATH];
    WCHAR devName[MAX_PATH];
    WCHAR fileName[MAX_PATH];
    HANDLE FindHandle = INVALID_HANDLE_VALUE;
    WCHAR  VolumeName[MAX_PATH];
    DWORD  Error = ERROR_SUCCESS;
    size_t Index = 0;
    DWORD  CharCount = MAX_PATH + 1;

    int index = 0;
    // \Device\HarddiskVolume1\windows,locate \windows.
    for (int i = 0; i < lstrlenW(filepath); i++) {
        if (!memcmp(&filepath[i], L"\\", 2)) {
            index++;
            if (index == 3) {
                index = i;
                break;
            }
        }
    }
    filepath[index] = L'\0';

    memcpy(fileDevName, filepath, (index + 1) * sizeof(WCHAR));

    FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));

    if (FindHandle == INVALID_HANDLE_VALUE)
    {
        Error = GetLastError();
        wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
        return FALSE;
    }
    for (;;)
    {
        //  Skip the \\?\ prefix and remove the trailing backslash.
        Index = wcslen(VolumeName) - 1;

        if (VolumeName[0] != L'\\' ||
            VolumeName[1] != L'\\' ||
            VolumeName[2] != L'?' ||
            VolumeName[3] != L'\\' ||
            VolumeName[Index] != L'\\')
        {
            Error = ERROR_BAD_PATHNAME;
            wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);
            break;
        }
        VolumeName[Index] = L'\0';
        CharCount = QueryDosDeviceW(&VolumeName[4], devName, 100);
        if (CharCount == 0)
        {
            Error = GetLastError();
            wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);
            break;
        }
        if (!lstrcmpW(devName, filepath)) {
            VolumeName[Index] = L'\\';
            Error = GetVolumePathNamesForVolumeNameW(VolumeName, fileName, CharCount, &CharCount);
            if (!Error) {
                Error = GetLastError();
                wprintf(L"GetVolumePathNamesForVolumeNameW failed with error code %d\n", Error);
                break;
            }

            // concat drive letter to path
            lstrcatW(fileName, &filepath[index + 1]);
            lstrcpyW(filepath, fileName);

            Error = ERROR_SUCCESS;
            break;
        }

        Error = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));

        if (!Error)
        {
            Error = GetLastError();

            if (Error != ERROR_NO_MORE_FILES)
            {
                wprintf(L"FindNextVolumeW failed with error code %d\n", Error);
                break;
            }

            //
            //  Finished iterating
            //  through all the volumes.
            Error = ERROR_BAD_PATHNAME;
            break;
        }
    }

    FindVolumeClose(FindHandle);
    if (Error != ERROR_SUCCESS)
        return FALSE;
    return TRUE;

}

如果您想在驱动程序中解析它,您可以检查此 链接供参考。

You can lookup all volumes' name to match a device name and get drive letter.Here is a sample:

int DeviceNameToVolumePathName(WCHAR *filepath) {
    WCHAR fileDevName[MAX_PATH];
    WCHAR devName[MAX_PATH];
    WCHAR fileName[MAX_PATH];
    HANDLE FindHandle = INVALID_HANDLE_VALUE;
    WCHAR  VolumeName[MAX_PATH];
    DWORD  Error = ERROR_SUCCESS;
    size_t Index = 0;
    DWORD  CharCount = MAX_PATH + 1;

    int index = 0;
    // \Device\HarddiskVolume1\windows,locate \windows.
    for (int i = 0; i < lstrlenW(filepath); i++) {
        if (!memcmp(&filepath[i], L"\\", 2)) {
            index++;
            if (index == 3) {
                index = i;
                break;
            }
        }
    }
    filepath[index] = L'\0';

    memcpy(fileDevName, filepath, (index + 1) * sizeof(WCHAR));

    FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));

    if (FindHandle == INVALID_HANDLE_VALUE)
    {
        Error = GetLastError();
        wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
        return FALSE;
    }
    for (;;)
    {
        //  Skip the \\?\ prefix and remove the trailing backslash.
        Index = wcslen(VolumeName) - 1;

        if (VolumeName[0] != L'\\' ||
            VolumeName[1] != L'\\' ||
            VolumeName[2] != L'?' ||
            VolumeName[3] != L'\\' ||
            VolumeName[Index] != L'\\')
        {
            Error = ERROR_BAD_PATHNAME;
            wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);
            break;
        }
        VolumeName[Index] = L'\0';
        CharCount = QueryDosDeviceW(&VolumeName[4], devName, 100);
        if (CharCount == 0)
        {
            Error = GetLastError();
            wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);
            break;
        }
        if (!lstrcmpW(devName, filepath)) {
            VolumeName[Index] = L'\\';
            Error = GetVolumePathNamesForVolumeNameW(VolumeName, fileName, CharCount, &CharCount);
            if (!Error) {
                Error = GetLastError();
                wprintf(L"GetVolumePathNamesForVolumeNameW failed with error code %d\n", Error);
                break;
            }

            // concat drive letter to path
            lstrcatW(fileName, &filepath[index + 1]);
            lstrcpyW(filepath, fileName);

            Error = ERROR_SUCCESS;
            break;
        }

        Error = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));

        if (!Error)
        {
            Error = GetLastError();

            if (Error != ERROR_NO_MORE_FILES)
            {
                wprintf(L"FindNextVolumeW failed with error code %d\n", Error);
                break;
            }

            //
            //  Finished iterating
            //  through all the volumes.
            Error = ERROR_BAD_PATHNAME;
            break;
        }
    }

    FindVolumeClose(FindHandle);
    if (Error != ERROR_SUCCESS)
        return FALSE;
    return TRUE;

}

If you want to resolve it in driver,you can check this link for reference.

面犯桃花 2024-07-14 03:50:09

这是解决方案的重构版本。

我用 wchar_t 替换了 TChAR,因为据我所知,在大多数项目中使用它并不是一个好主意。

std::map<std::wstring, std::wstring> GetDosPathDevicePathMap()
{
    // It's not really related to MAX_PATH, but I guess it should be enough.
    // Though the docs say "The first null-terminated string stored into the buffer is the current mapping for the device.
    //                      The other null-terminated strings represent undeleted prior mappings for the device."
    wchar_t devicePath[MAX_PATH] = { 0 };
    std::map<std::wstring, std::wstring> result;
    std::wstring dosPath = L"A:";

    for (wchar_t letter = L'A'; letter <= L'Z'; ++letter)
    {
        dosPath[0] = letter;
        if (QueryDosDeviceW(dosPath.c_str(), devicePath, MAX_PATH)) // may want to properly handle errors instead ... e.g. check ERROR_INSUFFICIENT_BUFFER
        {
            result[dosPath] = devicePath;
        }
    }
    return result;
}

Here is refactored version of the solution.

I replaced TChAR with wchar_t because afaik it's not a good idea to use it in most projects.

std::map<std::wstring, std::wstring> GetDosPathDevicePathMap()
{
    // It's not really related to MAX_PATH, but I guess it should be enough.
    // Though the docs say "The first null-terminated string stored into the buffer is the current mapping for the device.
    //                      The other null-terminated strings represent undeleted prior mappings for the device."
    wchar_t devicePath[MAX_PATH] = { 0 };
    std::map<std::wstring, std::wstring> result;
    std::wstring dosPath = L"A:";

    for (wchar_t letter = L'A'; letter <= L'Z'; ++letter)
    {
        dosPath[0] = letter;
        if (QueryDosDeviceW(dosPath.c_str(), devicePath, MAX_PATH)) // may want to properly handle errors instead ... e.g. check ERROR_INSUFFICIENT_BUFFER
        {
            result[dosPath] = devicePath;
        }
    }
    return result;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文