我遇到了大量非托管 C++/MFC 示例,这些示例显示人们试图通过其 DOS 路径确定驱动器的类型,但对于应该如何完成似乎存在很多困惑。所以我试图将所有信息整合到一个功能中,并做微软很久以前应该为我们做的事情。
我基本上需要将所有现代驱动器分类为:
- 固定驱动器
- 可移动驱动器
- 媒体驱动器
- 其他(见代码中的解释)
有人可以在下面检查我的代码吗?
enum DRIVE_TYPE2{
DT2_ERROR,
DT2_FIXED_DRIVE, //Any internal drive that cannot be removed while system is running, like a hard drive
DT2_REMOVABLE_DRIVE, //Removable drive. Example: Any USB drive
DT2_MEDIA_DRIVE, //CD/DVD drive, or a floppy drive
DT2_OTHER, //Other (rare) types, like virtual drive, RAM drive, etc.
};
static DRIVE_TYPE2 getDriveType(LPCTSTR pStrDriveDosPath)
{
//Determine the drive type by its DOS path
//'pStrDriveDosPath' = Path to the drive (example: "c:" or "d:") -- must be only a local drive letter!
//RETURN:
// = One of the values from the DRIVE_TYPE2 enum
ASSERT(pStrDriveDosPath);
DRIVE_TYPE2 res = DT2_ERROR;
//Make path
CString strPath;
strPath.Format(_T("\\\\.\\%s"), pStrDriveDosPath);
HANDLE hDevice = CreateFile(strPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if ( hDevice != INVALID_HANDLE_VALUE )
{
//First check for floppy discs
DISK_GEOMETRY Geom[20];
DWORD cb;
if(DeviceIoControl(hDevice, IOCTL_DISK_GET_MEDIA_TYPES, 0, 0, Geom, sizeof(Geom), &cb, 0)
&& cb > 0)
{
switch (Geom[0].MediaType)
{
case F5_1Pt2_512: // 5.25 1.2MB floppy
case F5_360_512: // 5.25 360K floppy
case F5_320_512: // 5.25 320K floppy
case F5_320_1024: // 5.25 320K floppy
case F5_180_512: // 5.25 180K floppy
case F5_160_512: // 5.25 160K floppy
case F5_640_512: //5.25", 640 KB, 512 bytes/sector media
case F5_720_512: //5.25", 720 KB, 512 bytes/sector media
case F5_1Pt23_1024: //5.25", 1.23 MB, 1024 bytes/sector media
case F3_1Pt44_512: // 3.5 1.44MB floppy
case F3_2Pt88_512: // 3.5 2.88MB floppy
case F3_20Pt8_512: // 3.5 20.8MB floppy
case F3_720_512: // 3.5 720K floppy
case F3_120M_512: //3.5", 120 MB media
case F3_640_512: //3.5", 640 KB, 512 bytes/sector media
case F3_1Pt2_512: //3.5", 1.2 MB, 512 bytes/sector media
case F3_1Pt23_1024: //3.5", 1.23 MB, 1024 bytes/sector media
case F3_128Mb_512: //3.5" magneto-optical (MO), 128 MB, 512 bytes/sector media
case F3_230Mb_512: //3.5" magneto-optical (MO), 230 MB, 512 bytes/sector media
case F8_256_128: //8", 256 KB, 128 bytes/sector media
case RemovableMedia:
res = DT2_MEDIA_DRIVE;
break;
}
}
//Did we get the type?
if(res == DT2_ERROR)
{
//Check for CD/DVD drive
UINT nDrvType = GetDriveType(pStrDriveDosPath + CString(_T("\\")));
switch(nDrvType)
{
case DRIVE_CDROM:
//Media drive
res = DT2_MEDIA_DRIVE;
break;
}
//Did we get the type?
if(res == DT2_ERROR)
{
//Then try by bus type
DWORD dwOutBytes = 0; // IOCTL output length
STORAGE_PROPERTY_QUERY Query; // input param for query
// specify the query type
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
char OutBuf[1024] = {0}; // good enough, usually about 100 bytes
PSTORAGE_DEVICE_DESCRIPTOR pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)OutBuf;
pDevDesc->Size = sizeof(OutBuf);
// Query using IOCTL_STORAGE_QUERY_PROPERTY
if(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))
{
//See by type
switch(pDevDesc->BusType)
{
case BusTypeAtapi:
case BusTypeAta:
case BusTypeRAID:
case BusTypeSas:
case BusTypeSata:
//Fixed
res = DT2_FIXED_DRIVE;
break;
case BusTypeScsi:
case BusType1394: //Firewire
case BusTypeSsa:
case BusTypeFibre:
case BusTypeUsb:
case BusTypeiScsi:
case BusTypeSd:
case BusTypeMmc:
//Removable
res = DT2_REMOVABLE_DRIVE;
break;
case BusTypeVirtual:
case BusTypeFileBackedVirtual:
//Other
res = DT2_OTHER;
break;
default:
//Error
ASSERT(pDevDesc->BusType == BusTypeUnknown);
res = DT2_ERROR;
break;
}
}
}
}
//Close drive handle
CloseHandle(hDevice);
}
return res;
}