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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/127124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:18:08  来源:igfitidea点击:

Resolve Windows device path to drive letter

windowspathdevice

提问by QAZ

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

你如何解析一个 NT 风格的设备路径,例如\Device\CdRom0,到它的逻辑驱动器号,例如G:\

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

编辑:卷名与设备路径不同,因此很遗憾GetVolumePathNamesForVolumeName()无法正常工作。

采纳答案by RichS

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

回答by Alex

Following function does the job using C only

以下函数仅使用 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] = '
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'
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;
}
'; 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'##代码##'; 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 (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); }

回答by Nick

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

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

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

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

(I haven't tried this)

(这个我没试过)

回答by VictorV

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

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

##代码##

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

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

回答by Alex P.

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.

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

##代码##