使用windows API区分移动硬盘和本地硬盘

       在程序中,有时候需要区分移动硬盘和本地硬盘,U盘的检测比较简单,首先用GetLogicalDriveStrings获取盘符,然后用GetDriveType获取类型,返回结果为DRIVE_REMOVABLE,则为U盘。这里有个问题,就是如果电脑中存在可移动磁盘的盘符,却没有插入移动磁盘,这时候如果试图打开这个磁盘,系统会提示你插入磁盘。所以,应该在检测到类型为DRIVE_REMOVABLE之后,再使用GetVolumeInformation获取卷信息,如果获取成功,则说明该盘符已插入磁盘。

       对于移动硬盘,使用GetDriveType返回的结果永远为DRIVE_FIXED,就是说系统将其与本地硬盘归为一类。那么,如何区分指定盘符是移动硬盘还是本地硬盘呢?

       首先用CreateFile通过指定的盘符打开设备,返回设备句柄,然后用DeviceIoControl获取设备信息,通过总线类型判断是否USB接入,如果总线类型为USB则是移动硬盘。

       代码如下:

bool CopyFileThread::checkRemoveDisk(vector* 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)