1. USB存储设备的标识
USB存储设备插入电脑之后,系统会给设备分配物理驱动器号、设备路径、卷路径。
1.1. 物理驱动器号
String | Meaning |
---|---|
\\.\PhysicalDrive0 | Opens the first physical drive. |
\\.\PhysicalDrive1 | Opens the third physical drive. |
1.2. 设备路径
DevicePath:
\\.\usbstor#disk&ven_usb&prod_flash_drive&rev_1.00#6&31e44d9c&3#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
1.3. 卷路径
卷又被称为逻辑驱动器。
VolumePath:
\\.\Volume{65f4b646-a379-11e9-a35f-005056c00008}
1.3.1 卷设备名
一个卷都对应一个卷设备名。
VolumeName:
\\.\HarddiskVolume57
1.3.2 逻辑驱动器号
逻辑驱动器号它是操作系统方便用户直接访问卷而建立的一个映射。
即给卷分配挂载点(Mount Point),可以通过SetVolumeMountPoint来实现。挂载点有两种形式,一种是直接分配逻辑盘符(Logic disk letter),另一种是卷文件夹(Mounted folder)。如C盘空间不够,电脑插入一个新的硬盘,我们可以直接将这个硬盘挂载到C盘下作为C盘的一个文件夹。
Logic Disk Letter:
H:\
2. 设备标识之间的关系
2.1. 通过逻辑盘符获取物理设备号
DWORD GetPhysicalDriveFromDiskLetter(char letter)
{
CHAR path[DISK_PATH_LEN] = {0};
sprintf(path, "\\\\.\\%c:", letter);
HANDLE hDevice = CreateFile(path, // drive to open
GENERIC_READ | GENERIC_WRITE, // access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, //share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attribute
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
return DWORD(-1);
}
DWORD readed = 0; // discard results
STORAGE_DEVICE_NUMBER ; //use this to get disk numbers
BOOL result = DeviceIoControl(
hDevice, // handle to device
IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
&number, // output buffer
sizeof(number), // size of output buffer
&readed, // number of bytes returned
NULL // OVERLAPPED structure
);
if (!result) // fail
{
fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
(void)CloseHandle(hDevice);
return (DWORD)-1;
}
//printf("%d %d %d\n\n", number.DeviceType, number.DeviceNumber, number.PartitionNumber);
(void)CloseHandle(hDevice);
return number.DeviceNumber;
}
2.2. 通过卷名获取物理设备号
DWORD GetPhysicalDriveFromVolumeName(LPCSTR lpcVolumeName)
{
CHAR path[DISK_PATH_LEN] = {0};
sprintf(path, "\\\\.\\%s", lpcVolumeName);
// 如:"\\.\Volume{f0a05445-2d33-11e6-9b0b-806e6f6e6963}"
HANDLE hDevice = CreateFile(path, // drive to open
GENERIC_READ | GENERIC_WRITE, // access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, //share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attribute
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
return DWORD(-1);
}
DWORD readed = 0; // discard results
STORAGE_DEVICE_NUMBER number; //use this to get disk numbers
BOOL result = DeviceIoControl(
hDevice, // handle to device
IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
&number, // output buffer
sizeof(number), // size of output buffer
&readed, // number of bytes returned
NULL // OVERLAPPED structure
);
if (!result) // fail
{
fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
(void)CloseHandle(hDevice);
return (DWORD)-1;
}
//printf("%d %d %d\n\n", number.DeviceType, number.DeviceNumber, number.PartitionNumber);
(void)CloseHandle(hDevice);
return number.DeviceNumber;
}
2.3 获取所有的逻辑盘符
int GetAllDisk(std::vector<CString>& vecDrives)
{
char szbuf[MAX_PATH] = {0};
GetLogicalDriveStringsA(MAX_PATH,szbuf);
int nCount = 0;
char * pDrive = szbuf;
for(int nlen =strlen(szbuf); nlen == 3 ;nCount++)
{
CString strDrive = pDrive;
vecDrives.push_back(strDrive);
pDrive +=4;
nlen = strlen(pDrive);
}
return nCount;
}
2.4. 获取所有的卷
int GetAllVolume(vector<CString>& vstrVolume)
{
CHAR DeviceName[MAX_PATH] = "";
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Found = FALSE;
size_t Index = 0;
BOOL Success = FALSE;
CHAR VolumeName[MAX_PATH] = "";
int nVolumeCnt = 0;
//
// Enumerate all volumes in the system.
FindHandle = FindFirstVolume(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
return 0;
}
for (;;)
{
//
// Skip the \\?\ prefix and remove the trailing backslash.
if (VolumeName[0] != L'\\' ||
VolumeName[1] != L'\\' ||
VolumeName[2] != L'?' ||
VolumeName[3] != L'\\' ||
VolumeName[Index] != L'\\')
{
Error = ERROR_BAD_PATHNAME;
break;
}
nVolumeCnt++;
vstrVolume.push_back(VolumeName);
// Move on to the next volume.
Success = FindNextVolume(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if ( !Success )
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_SUCCESS;
break;
}
}
FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
return nVolumeCnt;
}
2.5. 通过挂载点获取卷名
char szMountPointName[MAX_PATH]="J:\\";
char szVolumeName[MAX_PATH]="";
GetVolumeNameForVolumeMountPoint(szMountPointName,szVolumeName,MAX_PATH);
2.6. 遍历所有的卷、卷路径、挂载点
#include <windows.h>
#include <stdio.h>
void DisplayVolumePaths(
__in PWCHAR VolumeName
)
{
DWORD CharCount = MAX_PATH + 1;
PWCHAR Names = NULL;
PWCHAR NameIdx = NULL;
BOOL Success = FALSE;
for (;;)
{
//
// Allocate a buffer to hold the paths.
Names = (PWCHAR) new BYTE [CharCount * sizeof(WCHAR)];
if ( !Names )
{
//
// If memory can't be allocated, return.
return;
}
//
// Obtain all of the paths
// for this volume.
Success = GetVolumePathNamesForVolumeNameW(
VolumeName, Names, CharCount, &CharCount
);
if ( Success )
{
break;
}
if ( GetLastError() != ERROR_MORE_DATA )
{
break;
}
//
// Try again with the
// new suggested size.
delete [] Names;
Names = NULL;
}
if ( Success )
{
//
// Display the various paths.
for ( NameIdx = Names;
NameIdx[0] != L'\0';
NameIdx += wcslen(NameIdx) + 1 )
{
wprintf(L" %s", NameIdx);
}
wprintf(L"\n");
}
if ( Names != NULL )
{
delete [] Names;
Names = NULL;
}
return;
}
void __cdecl wmain(void)
{
DWORD CharCount = 0;
WCHAR DeviceName[MAX_PATH] = L"";
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Found = FALSE;
size_t Index = 0;
BOOL Success = FALSE;
WCHAR VolumeName[MAX_PATH] = L"";
//
// Enumerate all volumes in the system.
FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
return;
}
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;
}
//
// QueryDosDeviceW does not allow a trailing backslash,
// so temporarily remove it.
VolumeName[Index] = L'\0';
CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName, ARRAYSIZE(DeviceName));
VolumeName[Index] = L'\\';
if ( CharCount == 0 )
{
Error = GetLastError();
wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);
break;
}
wprintf(L"\nFound a device:\n %s", DeviceName);
wprintf(L"\nVolume name: %s", VolumeName);
wprintf(L"\nPaths:");
DisplayVolumePaths(VolumeName);
//
// Move on to the next volume.
Success = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if ( !Success )
{
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_SUCCESS;
break;
}
}
FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
return;
}
2.7. 获取所有的磁盘设备路径
DWORD GetAllDiskDevicePath(vector<CString>& vstrDevice)
{
GUID* guid = (GUID*)&GUID_DEVINTERFACE_DISK;
// Get device interface info set handle
// for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if ( hDevInfo == INVALID_HANDLE_VALUE ) {
return 0;
}
// Retrieve a context structure for a device interface
// of a device information set.
DWORD dwIndex = 0;
BOOL bRet = FALSE;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while ( true )
{
bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid);
if ( !bRet )
{
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);
if ( dwSize!=0 && dwSize<=sizeof(Buf) )
{
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd,
dwSize, &dwSize, &spdd);
if ( res )
{
vstrDevice.push_back(pspdidd->DevicePath);
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return dwIndex;
}