#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 cmdSENDCMDINPARAMS 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 commandbIDCmd = (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函数获取的,第一种方法测试过十几个硬盘都可以成功获取,但是第二种方法只有一两个硬盘测试成功。。。