ドライブのタイプを DOS パスで判別しようとしている管理されていない C++/MFC の例をたくさん見てきましたが、その方法については多くの混乱があるようです。そこで私は、すべての情報を 1 つの機能に統合し、Microsoft がずっと前に私たちのためにすべきだったことを実行しようとしています。
基本的に、最新のすべてのドライブを次のように分類する必要があります。
- 固定駆動
- リムーバブルドライブ
- メディア ドライブ
- その他 (コード内の説明を参照)
誰かが私のコードを以下でチェックできますか?
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;
}