65.9K
CodeProject 正在变化。 阅读更多。
Home

如何正确获取 USB 磁盘的驱动器号

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (39投票s)

2004年3月29日

CPOL

2分钟阅读

viewsIcon

359354

downloadIcon

11215

使用 DeviceIoControl 获取 USB 磁盘驱动器号。

Sample image

引言

我们知道 USB 磁盘应该像软盘一样,是一个可移动磁盘,并且现在被越来越广泛地使用。因为,USB 磁盘比旧的软盘更快、更可靠、更经济实惠。

因此,当我们想检查目标系统的某个磁盘或驱动器是否可移动时,我们可能会想到使用 API 函数 "GetDriveType()"。是的,它确实适用于某些 USB 设备,例如 16MB,32MB, 64MB,和 128MB。;-) 那么,通过 USB 通道连接到系统的可移动硬盘呢?- Windows 将它们报告为“固定磁盘”,并且使用“GetDriveType()”函数我们会得到相同的结果。

我们如何区分这些 USB ‘固定磁盘’ 和那些 IDE ‘固定磁盘’? 这是针对这种情况的解决方案。

背景

(为什么我想正确获取 USB 磁盘的驱动器盘符? 因为我想在插入新的 USB 驱动器时检查病毒。我们不应该忽视日益技术化的病毒:)

由于我们可以获得有关磁盘类型的基本信息(使用 API 函数 ‘GetDriveType()’),我们可能只想检查 ‘可移动硬盘’ 来验证其总线类型。 那么,我们将有两个步骤来获取 USB 磁盘的驱动器盘符

代码思路

1. 获取磁盘基本信息

switch ( GetDriveType( szDrvName ) ) 
{
 case 0: // The drive type cannot be determined.
 case 1: // The root directory does not exist.
 drivetype = DRVUNKNOWN;
 break;
 case DRIVE_REMOVABLE: // The drive can be removed from the drive.
 drivetype = DRVREMOVE;
 break;
 case DRIVE_CDROM: // The drive is a CD-ROM drive.
 break;
 case DRIVE_FIXED: // The disk cannot be removed from the drive.
 drivetype = DRVFIXED;
 break;
 case DRIVE_REMOTE: // The drive is a remote (network) drive.
 drivetype = DRVREMOTE;
 break;
 case DRIVE_RAMDISK: // The drive is a RAM disk.
 drivetype = DRVRAM;
 break;
}

以上代码基于 ‘文章 ID: Q161300 HOWTO: 使用 Win32’ 从 MSDN 确定驱动器类型。

2. 确定 ‘固定磁盘’ 的总线类型

现在,我们可以在 ‘case = DRIVE_FIXED’中嵌入我们的代码

打开我们现在获得的驱动器

hDevice = CreateFile(szBuf, 
  GENERIC_READ, 
  FILE_SHARE_READ | FILE_SHARE_WRITE, 
  NULL, OPEN_EXISTING, NULL, NULL);

如果我们打开了这个驱动器,使用 API GetDisksProperty() 检查它的 BUSTYPE

if(GetDisksProperty(hDevice, pDevDesc))
{
 if(pDevDesc->BusType == BusTypeUsb) // This is the ‘Check Point’!!! ;-)
 {
  // We store the drive letter here
  szMoveDiskName[k] = chFirstDriveFromMask(temp); 
  szMoveDiskName[0]=k;
  k++;
 }
}

完成对它的操作后,关闭这个驱动器

CloseHandle(hDevice);

3. GetDisksProperty() 如何工作?

/********************************************************
*
* FUNCTION: GetDisksProperty(HANDLE hDevice, 
* PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
*
* PURPOSE: get the info of specified device
*
******************************************************/
BOOL GetDisksProperty(HANDLE hDevice, 
  PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
{
 STORAGE_PROPERTY_QUERY Query; // input param for query
 DWORD dwOutBytes; // IOCTL output length
 BOOL bResult; // IOCTL return val

 // specify the query type
 Query.PropertyId = StorageDeviceProperty;
 Query.QueryType = PropertyStandardQuery;

 // Query using IOCTL_STORAGE_QUERY_PROPERTY 
 bResult = ::DeviceIoControl(hDevice, // device handle
 IOCTL_STORAGE_QUERY_PROPERTY, // info of device property
  &Query, sizeof(STORAGE_PROPERTY_QUERY), // input data buffer
  pDevDesc, pDevDesc->Size, // output data buffer
  &dwOutBytes, // out's length
  (LPOVERLAPPED)NULL); 

 return bResult;
}

注释

  1. 有一些结构没有注释,请参阅 usbdisks_src 获取它们。
  2. 软盘驱动器 (A: 或 B:) 在此演示中被报告为 USB 磁盘,并且很容易纠正这一点,只需将一些代码放入 ‘case = DRIVE_REMOVABLE:’;

历史

  • 2004-03-29 - 1st GO
© . All rights reserved.