//将该部分内容保存到.cpp文件中可直接编译运行,用于辨别驱动器的类型!
#define MEDIA_INFO_SIZE sizeof(GET_MEDIA_TYPES)+15*sizeof(DEVICE_MEDIA_INFO)
#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef enum _STORAGE_BUS_TYPE {
BusTypeUnknown = 0x00,
BusTypeScsi,
BusTypeAtapi,
BusTypeAta,
BusType1394,
BusTypeSsa,
BusTypeFibre,
BusTypeUsb,
BusTypeRAID,
BusTypeiScsi,
BusTypeSas,
BusTypeSata,
BusTypeSd,
BusTypeMmc,
BusTypeMax,
BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;
typedef enum _STORAGE_PROPERTY_ID {
StorageDeviceProperty = 0,
StorageAdapterProperty,
StorageDeviceIdProperty
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
typedef enum _STORAGE_QUERY_TYPE {
PropertyStandardQuery = 0,
PropertyExistsQuery,
PropertyMaskQuery,
PropertyQueryMaxDefined
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
typedef struct _STORAGE_PROPERTY_QUERY {
STORAGE_PROPERTY_ID PropertyId;
STORAGE_QUERY_TYPE QueryType;
unsigned char AdditionalParameters[1];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
unsigned long Version;
unsigned long Size;
unsigned char DeviceType;
unsigned char DeviceTypeModifier;
unsigned char RemovableMedia;
unsigned char CommandQueueing;
unsigned long VendorIdOffset;
unsigned long ProductIdOffset;
unsigned long ProductRevisionOffset;
unsigned long SerialNumberOffset;
STORAGE_BUS_TYPE BusType;
unsigned long RawPropertiesLength;
unsigned char RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
#include <windows.h>
#include <winioctl.h>
#include <iostream.h>
#include <string.h>
#include <tchar.h>
BOOL GetDriveGeometry(const TCHAR * filename, DISK_GEOMETRY * pdg)
{
HANDLE hDevice; // 设备句柄
BOOL bResult; // DeviceIoControl的返回结果
GET_MEDIA_TYPES *pmt; // 内部用的输出缓冲区
DWORD dwOutBytes; // 输出数据长度
// 打开设备
hDevice = ::CreateFile(filename, // 文件名
GENERIC_READ, // 软驱需要读盘
FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if (hDevice == INVALID_HANDLE_VALUE)
{
// 设备无法打开...
return FALSE;
}
// 用IOCTL_DISK_GET_DRIVE_GEOMETRY取磁盘参数
bResult = ::DeviceIoControl(hDevice, // 设备句柄
IOCTL_DISK_GET_DRIVE_GEOMETRY, // 取磁盘参数
NULL, 0, // 不需要输入数据
pdg, sizeof(DISK_GEOMETRY), // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
// 如果失败,再用IOCTL_STORAGE_GET_MEDIA_TYPES_EX取介质类型参数
if (!bResult)
{
pmt = (GET_MEDIA_TYPES *)new BYTE[MEDIA_INFO_SIZE];
bResult = ::DeviceIoControl(hDevice, // 设备句柄
IOCTL_STORAGE_GET_MEDIA_TYPES_EX, // 取介质类型参数
NULL, 0, // 不需要输入数据
pmt, MEDIA_INFO_SIZE, // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
if (bResult)
{
// 注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的
// 为简化程序,用memcpy代替如下多条赋值语句:
// pdg->MediaType = (MEDIA_TYPE)pmt->MediaInfo[0].DeviceSpecific.DiskInfo.MediaType;
// pdg->Cylinders = pmt->MediaInfo[0].DeviceSpecific.DiskInfo.Cylinders;
// pdg->TracksPerCylinder = pmt->MediaInfo[0].DeviceSpecific.DiskInfo.TracksPerCylinder;
// ... ...
::memcpy(pdg, pmt->MediaInfo, sizeof(DISK_GEOMETRY));
}
delete pmt;
}
// 关闭设备句柄
::CloseHandle(hDevice);
return (bResult);
}
int main()
{
TCHAR szBuf[256];
memset(szBuf,0,sizeof(szBuf));
DISK_GEOMETRY dg;
TCHAR sztmpPath[100] = _T("\\\\.\\");
TCHAR szPath[100] = _T("\\\\.\\");
HANDLE hDevice; // 设备句柄
BOOL bResult; // DeviceIoControl的返回结果
STORAGE_PROPERTY_QUERY Query; // input param for query
DWORD dwOutBytes; // IOCTL output length
STORAGE_DEVICE_DESCRIPTOR pDevDesc;
DWORD len = GetLogicalDriveStrings(sizeof(szBuf)/sizeof(TCHAR),szBuf);
for (TCHAR* s = szBuf; *s; s += strlen(s)+1)
{
LPCTSTR sDrivePath = s;
memcpy(szPath,sztmpPath,sizeof(szPath));
::_tcscat(szPath,sDrivePath);
int nSize = ::_tcslen(szPath);
szPath[nSize-1] = '\0';
BOOL bResult = GetDriveGeometry(szPath,&dg);
// 打开设备
hDevice = ::CreateFile(szPath, // 文件名
GENERIC_READ, // 软驱需要读盘
FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
return FALSE;
}
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
pDevDesc.Size = sizeof(STORAGE_DEVICE_DESCRIPTOR);
// 用 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);
if (bResult == FALSE)
{
CloseHandle(hDevice);
return 0;
}
UINT Type = pDevDesc.BusType;
switch(Type)
{
case BusTypeUnknown:
cout<<sDrivePath<<" 未知设备"<<'\n';
break;
case BusTypeScsi:
cout<<sDrivePath<<" SCSI设备"<<'\n';
break;
case BusTypeAtapi:
cout<<sDrivePath<<" API设备"<<'\n';
break;
case BusTypeAta:
cout<<sDrivePath<<" ATA设备"<<'\n';
break;
case BusType1394:
cout<<sDrivePath<<" 1394设备"<<'\n';
break;
case BusTypeSsa:
cout<<sDrivePath<<" SSA设备"<<'\n';
break;
case BusTypeFibre:
cout<<sDrivePath<<" 光纤设备"<<'\n';
break;
case BusTypeUsb:
cout<<sDrivePath<<" USB设备"<<'\n';
break;
case BusTypeRAID:
cout<<sDrivePath<<" RAID设备"<<'\n';
break;
case BusTypeiScsi:
cout<<sDrivePath<<" iSCSI设备"<<'\n';
break;
case BusTypeSas:
cout<<sDrivePath<<" SAS设备"<<'\n';
break;
case BusTypeSata:
cout<<sDrivePath<<" SATA设备"<<'\n';
break;
case BusTypeSd:
cout<<sDrivePath<<" SD设备"<<'\n';
break;
case BusTypeMmc:
cout<<sDrivePath<<" MMC设备"<<'\n';
break;
case BusTypeMax:
cout<<sDrivePath<<" MAX设备"<<'\n';
break;
case BusTypeMaxReserved:
cout<<sDrivePath<<" ...设备"<<'\n';
break;
default:
break;
}
CloseHandle(hDevice);
}
};
欢迎大家加入"数据恢复技术"QQ群:30481379
本QQ群主要研究分析NTFS、EXT2/3、ResierFS等文件系统及数据恢复技术,同时对各种系统的磁盘阵列恢复的阵列参数智能分析算法进行技术交流,欢迎有志同道合者加入!
由于本群主要面向数据恢复的技术研究,同时起点要高于一般的数据恢复技术,所以希望加入者在加入本群以前已经有关于这方面技术的积累会相关研究经验,希望大家能理解!
本文出自 “数据恢复技术-Thinking..” 博客,转载请与作者联系!