如何将NT风格的设备路径(例如<code>DeviceCdRom0</code>)解析为其逻辑驱动器号(例如<code>g:
编辑:卷名与设备路径不同,因此很遗憾GetVolumePathNamesForVolumeName()
无法工作。
如何将NT风格的设备路径(例如<code>DeviceCdRom0</code>)解析为其逻辑驱动器号(例如<code>g:
编辑:卷名与设备路径不同,因此很遗憾GetVolumePathNamesForVolumeName()
无法工作。
希望下面的代码能为您提供足够的解决方案——在初始化它之后,您只需要遍历集合即可找到匹配项。在插入集合之前,您可能需要将所有内容转换为大写/小写,以帮助提高查找性能。
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 ) );
}
}
}
也许您可以使用GetVolumeNameForMountPoint并迭代所有装载点A:到Z:,在找到匹配项时中断?
http://msdn.microsoft.com/en-us/library/aa364994(VS.85).aspx
(我还没试过)
以下函数仅使用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] = ;
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);
}
您可以查找所有卷的名称以匹配设备名称并获取驱动器号。以下是示例:
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;
// DeviceHarddiskVolume1windows,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 ;
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
", 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
", VolumeName);
break;
}
VolumeName[Index] = L ;
CharCount = QueryDosDeviceW(&VolumeName[4], devName, 100);
if (CharCount == 0)
{
Error = GetLastError();
wprintf(L"QueryDosDeviceW failed with error code %d
", 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
", 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
", Error);
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_BAD_PATHNAME;
break;
}
}
FindVolumeClose(FindHandle);
if (Error != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
如果你想在驱动程序中解决它,你可以检查这个链接以供参考。
这是解决方案的重构版本。
我用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;
}