使用windows API区分移动硬盘和本地硬盘
2013-04-03 17:29
1106 查看
在程序中,有时候需要区分移动硬盘和本地硬盘,U盘的检测比较简单,首先用GetLogicalDriveStrings获取盘符,然后用GetDriveType获取类型,返回结果为DRIVE_REMOVABLE,则为U盘。这里有个问题,就是如果电脑中存在可移动磁盘的盘符,却没有插入移动磁盘,这时候如果试图打开这个磁盘,系统会提示你插入磁盘。所以,应该在检测到类型为DRIVE_REMOVABLE之后,再使用GetVolumeInformation获取卷信息,如果获取成功,则说明该盘符已插入磁盘。
对于移动硬盘,使用GetDriveType返回的结果永远为DRIVE_FIXED,就是说系统将其与本地硬盘归为一类。那么,如何区分指定盘符是移动硬盘还是本地硬盘呢?
首先用CreateFile通过指定的盘符打开设备,返回设备句柄,然后用DeviceIoControl获取设备信息,通过总线类型判断是否USB接入,如果总线类型为USB则是移动硬盘。
代码如下:
bool CopyFileThread::checkRemoveDisk(vector<LPTSTR>* drivePath) //参数存储所有移动盘的盘符
{
bool flag=false;
DWORD dw=GetLogicalDriveStrings(0,NULL);
LPTSTR lpDriveStrings=(LPTSTR)HeapAlloc(GetProcessHeap(),0,dw*sizeof(TCHAR));
GetLogicalDriveStrings(dw,lpDriveStrings); //获取盘符,字符串形式。
do
{
UINT drivetype=GetDriveType(lpDriveStrings); //获取驱动器类型
if(drivetype==DRIVE_REMOVABLE)
//驱动器类型为DRIVE_REMOVABLE,进一步获取卷信息,如果获取成功,则将盘符保存。
{
TCHAR szFileSNBuffer[512];
DWORD dwFSystemFlags;
//获取卷信息,如果获取成功,则说明已插入U盘。
if(GetVolumeInformation(lpDriveStrings,NULL,0,NULL,NULL,&dwFSystemFlags,szFileSNBuffer,512))
{
drivePath->push_back(lpDriveStrings);
flag=true;
}
}
else if(drivetype==DRIVE_FIXED) //驱动器类型为DRIVE_FIXED,需要进一步判断是移动硬盘还是本地硬盘。
{
if(GetDisksProperty( lpDriveStrings)==TRUE) //GetDisksProperty区分移动硬盘和本地硬盘,返回TRUE为移动硬盘.
{
drivePath->push_back(lpDriveStrings);
flag=true;
}
}
lpDriveStrings+=(lstrlen(lpDriveStrings)+1);
}
while(*lpDriveStrings!='\x00');
return flag;
}
GetDisksProperty定义如下:
BOOL CopyFileThread::GetDisksProperty(TCHAR *drive)
{
STORAGE_PROPERTY_QUERY Query;
DWORD dwOutBytes;
BOOL bResult;
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
CString cstr(drive);
cstr="\\\\.\\"+cstr;
cstr.Delete(cstr.GetLength()-1,1);
HANDLE hDevice=CreateFile(
cstr, // 要打开的驱动器设备;格式必须为“\\.\C:”,否则打开失败,返回错误码2:系统找不到指定的文件。
GENERIC_READ | GENERIC_WRITE, // 访问权限
FILE_SHARE_READ | FILE_SHARE_WRITE, //共享模式
NULL, // 使用默认的安全属性
OPEN_EXISTING, // 打开存在的设备
NULL,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE)
{
return FALSE;
}
STORAGE_DESCRIPTOR_HEADER *pDevDescHeader;
pDevDescHeader = (STORAGE_DESCRIPTOR_HEADER *)malloc(sizeof(STORAGE_DESCRIPTOR_HEADER));
if (NULL == pDevDescHeader)
{
return FALSE;
}
bResult = DeviceIoControl(
hDevice, // 设备句柄
IOCTL_STORAGE_QUERY_PROPERTY, // 操作控制码
&Query,sizeof Query, //输入参数及缓冲区大小
pDevDescHeader, //输出参数
sizeof(STORAGE_DESCRIPTOR_HEADER), //输出参数的缓冲区大小
&dwOutBytes, //实际输出的大小
NULL);
if (!bResult)
{
free(pDevDescHeader);
(void)CloseHandle(hDevice);
return FALSE;
}
PSTORAGE_DEVICE_DESCRIPTOR pDevDesc;
pDevDesc=(STORAGE_DEVICE_DESCRIPTOR *)malloc(pDevDescHeader->Size);
bResult = DeviceIoControl(hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query, sizeof Query,
pDevDesc, pDevDescHeader->Size,
&dwOutBytes,
NULL);
free(pDevDescHeader);
(void)CloseHandle(hDevice);
if(pDevDesc->BusType==BusTypeUsb)//总线类型为USB,返回TRUE
{
free(pDevDesc);
return TRUE;
}
free(pDevDesc);
return FALSE;
}
对于移动硬盘,使用GetDriveType返回的结果永远为DRIVE_FIXED,就是说系统将其与本地硬盘归为一类。那么,如何区分指定盘符是移动硬盘还是本地硬盘呢?
首先用CreateFile通过指定的盘符打开设备,返回设备句柄,然后用DeviceIoControl获取设备信息,通过总线类型判断是否USB接入,如果总线类型为USB则是移动硬盘。
代码如下:
bool CopyFileThread::checkRemoveDisk(vector<LPTSTR>* drivePath) //参数存储所有移动盘的盘符
{
bool flag=false;
DWORD dw=GetLogicalDriveStrings(0,NULL);
LPTSTR lpDriveStrings=(LPTSTR)HeapAlloc(GetProcessHeap(),0,dw*sizeof(TCHAR));
GetLogicalDriveStrings(dw,lpDriveStrings); //获取盘符,字符串形式。
do
{
UINT drivetype=GetDriveType(lpDriveStrings); //获取驱动器类型
if(drivetype==DRIVE_REMOVABLE)
//驱动器类型为DRIVE_REMOVABLE,进一步获取卷信息,如果获取成功,则将盘符保存。
{
TCHAR szFileSNBuffer[512];
DWORD dwFSystemFlags;
//获取卷信息,如果获取成功,则说明已插入U盘。
if(GetVolumeInformation(lpDriveStrings,NULL,0,NULL,NULL,&dwFSystemFlags,szFileSNBuffer,512))
{
drivePath->push_back(lpDriveStrings);
flag=true;
}
}
else if(drivetype==DRIVE_FIXED) //驱动器类型为DRIVE_FIXED,需要进一步判断是移动硬盘还是本地硬盘。
{
if(GetDisksProperty( lpDriveStrings)==TRUE) //GetDisksProperty区分移动硬盘和本地硬盘,返回TRUE为移动硬盘.
{
drivePath->push_back(lpDriveStrings);
flag=true;
}
}
lpDriveStrings+=(lstrlen(lpDriveStrings)+1);
}
while(*lpDriveStrings!='\x00');
return flag;
}
GetDisksProperty定义如下:
BOOL CopyFileThread::GetDisksProperty(TCHAR *drive)
{
STORAGE_PROPERTY_QUERY Query;
DWORD dwOutBytes;
BOOL bResult;
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
CString cstr(drive);
cstr="\\\\.\\"+cstr;
cstr.Delete(cstr.GetLength()-1,1);
HANDLE hDevice=CreateFile(
cstr, // 要打开的驱动器设备;格式必须为“\\.\C:”,否则打开失败,返回错误码2:系统找不到指定的文件。
GENERIC_READ | GENERIC_WRITE, // 访问权限
FILE_SHARE_READ | FILE_SHARE_WRITE, //共享模式
NULL, // 使用默认的安全属性
OPEN_EXISTING, // 打开存在的设备
NULL,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE)
{
return FALSE;
}
STORAGE_DESCRIPTOR_HEADER *pDevDescHeader;
pDevDescHeader = (STORAGE_DESCRIPTOR_HEADER *)malloc(sizeof(STORAGE_DESCRIPTOR_HEADER));
if (NULL == pDevDescHeader)
{
return FALSE;
}
bResult = DeviceIoControl(
hDevice, // 设备句柄
IOCTL_STORAGE_QUERY_PROPERTY, // 操作控制码
&Query,sizeof Query, //输入参数及缓冲区大小
pDevDescHeader, //输出参数
sizeof(STORAGE_DESCRIPTOR_HEADER), //输出参数的缓冲区大小
&dwOutBytes, //实际输出的大小
NULL);
if (!bResult)
{
free(pDevDescHeader);
(void)CloseHandle(hDevice);
return FALSE;
}
PSTORAGE_DEVICE_DESCRIPTOR pDevDesc;
pDevDesc=(STORAGE_DEVICE_DESCRIPTOR *)malloc(pDevDescHeader->Size);
bResult = DeviceIoControl(hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query, sizeof Query,
pDevDesc, pDevDescHeader->Size,
&dwOutBytes,
NULL);
free(pDevDescHeader);
(void)CloseHandle(hDevice);
if(pDevDesc->BusType==BusTypeUsb)//总线类型为USB,返回TRUE
{
free(pDevDesc);
return TRUE;
}
free(pDevDesc);
return FALSE;
}
相关文章推荐
- windows的磁盘操作之九――区分本地磁盘与移动硬盘
- windows的磁盘操作之九——区分本地磁盘与移动硬盘
- Windows的磁盘操作之九——区分本地磁盘与移动硬盘
- 区分挂载的分区是否是移动硬盘并返回最大剩余空间的本地磁盘
- windows的磁盘操作之九——区分本地磁盘与移动硬盘
- windows的磁盘操作之九——区分本地磁盘与移动硬盘
- windows的磁盘操作之九——区分本地磁盘与移动硬盘
- 使用移动硬盘在XP上安装Linux双系统
- 使用移动硬盘拷贝大文件到ubuntu系统
- Mac OS使用NTFS格式移动硬盘
- 移动硬盘的使用技巧
- WIN/MAC使用exFat格式共用移动硬盘
- 关于mac和windows使用移动硬盘的问题
- 磁盘必须经过初始化,逻辑磁盘管理器才能访问——笔记本硬盘作为移动硬盘使用时遇到的问题
- Mac: Mac系统从移动硬盘往外考资料时提示“不能更改xx中的一个或多个项目,因为它们正在使用中”压根就没开始用
- 使用MBROSTool 工具制作本地硬盘多启动盘的方法总结
- 移动硬盘分区变为RAW,chkdsk提示“因另一个程序正在使用这个卷,无法运行CHKDSK“ 的解决办法 .
- 关于mac和windows使用移动硬盘的问题
- Windows XP下使用NTFS格式加密移动硬盘
- Linux上如何使用移动硬盘?