#include "stdafx.h"
#include <WinIOCtl.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
#define PHYSICAL_DRIVE_NUMBER 0
#define DFP_GET_VERSION 0x00074080
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
// Valid values for the bCommandReg member of IDEREGS.
#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.
typedef struct _GETVERSIONOUTPARAMS
{
BYTE bVersion; // Binary driver version.
BYTE bRevision; // Binary driver revision.
BYTE bReserved; // Not used.
BYTE bIDEDeviceMap; // Bit map of IDE devices.
DWORD fCapabilities; // Bit mask of driver capabilities.
DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
// GETVERSIONOUTPARAMS contains the data returned from the
// Get Driver Version function.
CString csPhysical;
csPhysical.Format(_T("\\\\.\\PhysicalDrive%d"), PHYSICAL_DRIVE_NUMBER);
HANDLE hPhysical = ::CreateFile(csPhysical,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hPhysical != INVALID_HANDLE_VALUE)
{
//第一种方法
GETVERSIONOUTPARAMS VersionParams;
DWORD dwRet = sizeof(VersionParams);
if (::DeviceIoControl(hPhysical,
DFP_GET_VERSION,
NULL, 0,
&VersionParams, sizeof(VersionParams),
&dwRet, NULL))
{
if (VersionParams.bIDEDeviceMap > 0)
{
BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd
SENDCMDINPARAMS scip;
BYTE IdOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
// Now, get the ID sector for all IDE devices in the system.
// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
// otherwise use the IDE_ATA_IDENTIFY command
bIDCmd = (VersionParams.bIDEDeviceMap >> PHYSICAL_DRIVE_NUMBER & 0x10) ? \
IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset(IdOutCmd, 0, sizeof(IdOutCmd));
memset(&scip, 0, sizeof(scip));
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bFeaturesReg = 0;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bSectorNumberReg = 1;
scip.irDriveRegs.bCylLowReg = 0;
scip.irDriveRegs.bCylHighReg = 0;
// Compute the drive number.
scip.irDriveRegs.bDriveHeadReg = 0xA0 | ((PHYSICAL_DRIVE_NUMBER & 1) << 4);
// The command can either be IDE identify or ATAPI identify.
scip.irDriveRegs.bCommandReg = bIDCmd;
scip.bDriveNumber = PHYSICAL_DRIVE_NUMBER;
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
if (DeviceIoControl(hPhysical,
DFP_RECEIVE_DRIVE_DATA,
&scip,
sizeof(SENDCMDINPARAMS) - 1,
IdOutCmd,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
&dwRet, NULL))
{
printf("Serial Number = ");
for (DWORD i = 0; i < 20; i += 2)
{
putchar(((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer[i + 10 * sizeof(TCHAR) + 1]);
putchar(((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer[i + 10 * sizeof(TCHAR)]);
}
putchar('\n');
}
else
{
printf("DeviceIoControl DFP_RECEIVE_DRIVE_DATA Fail, Error Code: %d\n", ::GetLastError());
}
}
}
else
{
printf("DeviceIoControl DFP_GET_VERSION Fail, Error Code: %d\n", ::GetLastError());
}
//第二种方法
BYTE pBuffer[8192] = { 0 };
STORAGE_PROPERTY_QUERY spq;
memset(&spq, 0, sizeof(STORAGE_PROPERTY_QUERY));
spq.PropertyId = StorageDeviceProperty;
spq.QueryType = PropertyStandardQuery;
if (::DeviceIoControl(hPhysical,
IOCTL_STORAGE_QUERY_PROPERTY,
&spq, sizeof(STORAGE_PROPERTY_QUERY),
pBuffer, sizeof(pBuffer),
&dwRet, NULL))
{
DWORD dwStart = ((PSTORAGE_DEVICE_DESCRIPTOR)pBuffer)->SerialNumberOffset;
printf("Serial Number = ");
while (TRUE)
{
CHAR cSN = (CHAR)pBuffer[dwStart++];
if (cSN == '\0') break;
putchar(cSN);
}
putchar('\n');
}
else
{
printf("DeviceIoControl IOCTL_STORAGE_QUERY_PROPERTY Fail, Error Code: %d\n", ::GetLastError());
}
::CloseHandle(hPhysical);
}
system("pause");
}
return nRetCode;
}
这个是用DeviceIoControl函数获取的,第一种方法测试过十几个硬盘都可以成功获取,但是第二种方法只有一两个硬盘测试成功。。。