📄 getidediskinfo.cpp
字号:
#include "stdafx.h"#include "GetIdeDiskInfo.h"
// 打开设备
// filename: 设备的“文件名”
HANDLE OpenDevice(LPCTSTR filename)
{
HANDLE hDevice;
// 打开设备
hDevice= ::CreateFile(filename, // 文件名
GENERIC_READ | GENERIC_WRITE, // 读写方式
FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
return hDevice;
}
// 向驱动发“IDENTIFY DEVICE”命令,获得设备信息
// hDevice: 设备句柄
// pIdInfo: 设备信息结构指针
BOOL IdentifyDevice(HANDLE hDevice, PIDINFO pIdInfo)
{
PSENDCMDINPARAMS pSCIP; // 输入数据结构指针
PSENDCMDOUTPARAMS pSCOP; // 输出数据结构指针
DWORD dwOutBytes; // IOCTL输出数据长度
BOOL bResult; // IOCTL返回值
// 申请输入/输出数据结构空间
pSCIP = (PSENDCMDINPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDINPARAMS)-1);
pSCOP = (PSENDCMDOUTPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1);
// 指定ATA/ATAPI命令的寄存器值
// pSCIP->irDriveRegs.bFeaturesReg = 0;
// pSCIP->irDriveRegs.bSectorCountReg = 0;
// pSCIP->irDriveRegs.bSectorNumberReg = 0;
// pSCIP->irDriveRegs.bCylLowReg = 0;
// pSCIP->irDriveRegs.bCylHighReg = 0;
// pSCIP->irDriveRegs.bDriveHeadReg = 0;
pSCIP->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
// 指定输入/输出数据缓冲区大小
pSCIP->cBufferSize = 0;
pSCOP->cBufferSize = sizeof(IDINFO);
// IDENTIFY DEVICE
bResult = ::DeviceIoControl(hDevice, // 设备句柄
DFP_RECEIVE_DRIVE_DATA, // 指定IOCTL
pSCIP, sizeof(SENDCMDINPARAMS) - 1, // 输入数据缓冲区
pSCOP, sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1, // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
// 复制设备参数结构
::memcpy(pIdInfo, pSCOP->bBuffer, sizeof(IDINFO));
// 释放输入/输出数据空间
::GlobalFree(pSCOP);
::GlobalFree(pSCIP);
return bResult;
}
// 向SCSI MINI-PORT驱动发“IDENTIFY PACKET DEVICE”命令,获得设备信息
// hDevice: 设备句柄
// pIdInfo: 设备信息结构指针
BOOL IdentifyDeviceAsScsi(HANDLE hDevice, int nDrive, PIDINFO pIdInfo)
{
PSENDCMDINPARAMS pSCIP; // 输入数据结构指针
PSENDCMDOUTPARAMS pSCOP; // 输出数据结构指针
PSRB_IO_CONTROL pSRBIO; // SCSI输入输出数据结构指针
DWORD dwOutBytes; // IOCTL输出数据长度
BOOL bResult; // IOCTL返回值
// 申请输入/输出数据结构空间
pSRBIO = (PSRB_IO_CONTROL)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1);
pSCIP = (PSENDCMDINPARAMS)((char *)pSRBIO+sizeof(SRB_IO_CONTROL));
pSCOP = (PSENDCMDOUTPARAMS)((char *)pSRBIO+sizeof(SRB_IO_CONTROL));
// 填充输入/输出数据
pSRBIO->HeaderLength = sizeof(SRB_IO_CONTROL);
pSRBIO->Timeout = 10000;
pSRBIO->Length = sizeof(SENDCMDOUTPARAMS)+sizeof(IDINFO)-1;
pSRBIO->ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
::strncpy ((char *)pSRBIO->Signature, "SCSIDISK", 8);
// 指定ATA/ATAPI命令的寄存器值
// pSCIP->irDriveRegs.bFeaturesReg = 0;
// pSCIP->irDriveRegs.bSectorCountReg = 0;
// pSCIP->irDriveRegs.bSectorNumberReg = 0;
// pSCIP->irDriveRegs.bCylLowReg = 0;
// pSCIP->irDriveRegs.bCylHighReg = 0;
// pSCIP->irDriveRegs.bDriveHeadReg = 0;
pSCIP->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
pSCIP->bDriveNumber = nDrive;
// IDENTIFY DEVICE
bResult = ::DeviceIoControl(hDevice, // 设备句柄
IOCTL_SCSI_MINIPORT, // 指定IOCTL
pSRBIO, sizeof(SRB_IO_CONTROL) +sizeof(SENDCMDINPARAMS) - 1, // 输入数据缓冲区
pSRBIO, sizeof(SRB_IO_CONTROL) +sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1, // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
// 复制设备参数结构
::memcpy(pIdInfo, pSCOP->bBuffer, sizeof(IDINFO));
// 释放输入/输出数据空间
::GlobalFree(pSRBIO);
return bResult;
}
// 将串中的字符两两颠倒
// 原因是ATA/ATAPI中的WORD,与Windows采用的字节顺序相反
// 驱动程序中已经将收到的数据全部反过来,我们来个负负得正
void AdjustString(char* str, int len)
{
char ch;
int i;
// 两两颠倒
for(i=0;i<len;i+=2)
{
ch = str[i];
str[i] = str[i+1];
str[i+1] = ch;
}
// 若是右对齐的,调整为左对齐 (去掉左边的空格)
i=0;
while(i<len && str[i]==' ') i++;
::memmove(str, &str[i], len-i);
// 去掉右边的空格
i = len - 1;
while(i>=0 && str[i]==' ')
{
str[i] = '\0';
i--;
}
}
// 读取IDE硬盘的设备信息,必须有足够权限
// nDrive: 驱动器号(0=第一个硬盘,1=0=第二个硬盘,......)
// pIdInfo: 设备信息结构指针
BOOL GetPhysicalDriveInfoInNT(int nDrive, PIDINFO pIdInfo)
{
HANDLE hDevice; // 设备句柄
BOOL bResult; // 返回结果
char szFileName[20]; // 文件名
::sprintf(szFileName,"\\\\.\\PhysicalDrive%d", nDrive);
hDevice = ::OpenDevice(szFileName);
if(hDevice == INVALID_HANDLE_VALUE)
{
return FALSE;
}
// IDENTIFY DEVICE
bResult = ::IdentifyDevice(hDevice, pIdInfo);
if(bResult)
{
// 调整字符串
::AdjustString(pIdInfo->sSerialNumber, 20);
::AdjustString(pIdInfo->sModelNumber, 40);
::AdjustString(pIdInfo->sFirmwareRev, 8);
}
::CloseHandle (hDevice);
return bResult;
}
// 用SCSI驱动读取IDE硬盘的设备信息,不受权限制约
// nDrive: 驱动器号(0=Primary Master, 1=Promary Slave, 2=Secondary master, 3=Secondary slave)
// pIdInfo: 设备信息结构指针
BOOL GetIdeDriveAsScsiInfoInNT(int nDrive, PIDINFO pIdInfo)
{
HANDLE hDevice; // 设备句柄
BOOL bResult; // 返回结果
char szFileName[20]; // 文件名
::sprintf(szFileName,"\\\\.\\Scsi%d:", nDrive/2);
hDevice = ::OpenDevice(szFileName);
if(hDevice == INVALID_HANDLE_VALUE)
{
return FALSE;
}
// IDENTIFY DEVICE
bResult = ::IdentifyDeviceAsScsi(hDevice, nDrive%2, pIdInfo);
// 检查是不是空串
if(pIdInfo->sModelNumber[0]=='\0')
{
bResult = FALSE;
}
if(bResult)
{
// 调整字符串
::AdjustString(pIdInfo->sSerialNumber, 20);
::AdjustString(pIdInfo->sModelNumber, 40);
::AdjustString(pIdInfo->sFirmwareRev, 8);
}
return bResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -