获取硬盘的smart信息
Posted ziqiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取硬盘的smart信息相关的知识,希望对你有一定的参考价值。
SMART 数据储存于 WMI 中 ROOTWMIMSStorageDriver_ATASmartData 命名空间中,其中属性 ‘VendorSpecific‘ 包含有硬盘温度的数据,这是ATA标准定义的。这是一个结构大小为512字节,第一个和第二个字节代表 SMART 版本信息,从第三个字节起定义 SMART 的属性,每个属性为12字节长,每个属性的第一字节为当前属性定义,0x09 定义已经使用的小时数, 0xc2 为温度属性,第五字节表示当前温度。
本人尚处学习阶段,如有不足或错误之处,欢迎指出。
头文件:
#include <stdio.h> #include <windows.h> #include <WinIoCtl.h> #include <stdlib.h> #include <string.h> #include <tchar.h> #define MAX_ATTRIBUTE 30 bool Getsmart(int driver); void capacity(char* model_buf, char* sn_buf, char* fw_buf); void GetDisksmart(WORD count,DWORD driver, CHAR *modelNumber, CHAR *sn_buf, CHAR * fw_buf ); void ChangeByteOrder(PCHAR szString, USHORT uscStrSize); #pragma pack (1) typedef struct ATA_IDENTIFY_DEVICE { WORD GeneralConfiguration; //0 WORD LogicalCylinders; //1 Obsolete WORD SpecificConfiguration; //2 WORD LogicalHeads; //3 Obsolete WORD Retired1[2]; //4-5 WORD LogicalSectors; //6 Obsolete DWORD ReservedForCompactFlash; //7-8 WORD Retired2; //9 CHAR SerialNumber[20]; //10-19 WORD Retired3; //20 WORD BufferSize; //21 Obsolete WORD Obsolute4; //22 CHAR FirmwareRev[8]; //23-26 CHAR Model[40]; //27-46 WORD MaxNumPerInterupt; //47 WORD Reserved1; //48 WORD Capabilities1; //49 WORD Capabilities2; //50 DWORD Obsolute5; //51-52 WORD Field88and7064; //53 WORD Obsolute6[5]; //54-58 WORD MultSectorStuff; //59 DWORD TotalAddressableSectors; //60-61 WORD Obsolute7; //62 WORD MultiWordDma; //63 WORD PioMode; //64 WORD MinMultiwordDmaCycleTime; //65 WORD RecommendedMultiwordDmaCycleTime; //66 WORD MinPioCycleTimewoFlowCtrl; //67 WORD MinPioCycleTimeWithFlowCtrl; //68 WORD Reserved2[6]; //69-74 WORD QueueDepth; //75 WORD SerialAtaCapabilities; //76 WORD SerialAtaAdditionalCapabilities; //77 WORD SerialAtaFeaturesSupported; //78 WORD SerialAtaFeaturesEnabled; //79 WORD MajorVersion; //80 WORD MinorVersion; //81 WORD CommandSetSupported1; //82 WORD CommandSetSupported2; //83 WORD CommandSetSupported3; //84 WORD CommandSetEnabled1; //85 WORD CommandSetEnabled2; //86 WORD CommandSetDefault; //87 WORD UltraDmaMode; //88 WORD TimeReqForSecurityErase; //89 WORD TimeReqForEnhancedSecure; //90 WORD CurrentPowerManagement; //91 WORD MasterPasswordRevision; //92 WORD HardwareResetResult; //93 WORD AcoustricManagement; //94 WORD StreamMinRequestSize; //95 WORD StreamingTimeDma; //96 WORD StreamingAccessLatency; //97 DWORD StreamingPerformance; //98-99 ULONGLONG MaxUserLba; //100-103 WORD StremingTimePio; //104 WORD Reserved3; //105 WORD SectorSize; //106 WORD InterSeekDelay; //107 WORD IeeeOui; //108 WORD UniqueId3; //109 WORD UniqueId2; //110 WORD UniqueId1; //111 WORD Reserved4[4]; //112-115 WORD Reserved5; //116 DWORD WordsPerLogicalSector; //117-118 WORD Reserved6[8]; //119-126 WORD RemovableMediaStatus; //127 WORD SecurityStatus; //128 WORD VendorSpecific[31]; //129-159 WORD CfaPowerMode1; //160 WORD ReservedForCompactFlashAssociation[7]; //161-167 WORD DeviceNominalFormFactor; //168 WORD DataSetManagement; //169 WORD AdditionalProductIdentifier[4]; //170-173 WORD Reserved7[2]; //174-175 CHAR CurrentMediaSerialNo[60]; //176-205 WORD SctCommandTransport; //206 WORD ReservedForCeAta1[2]; //207-208 WORD AlignmentOfLogicalBlocks; //209 DWORD WriteReadVerifySectorCountMode3; //210-211 DWORD WriteReadVerifySectorCountMode2; //212-213 WORD NvCacheCapabilities; //214 DWORD NvCacheSizeLogicalBlocks; //215-216 WORD NominalMediaRotationRate; //217 WORD Reserved8; //218 WORD NvCacheOptions1; //219 WORD NvCacheOptions2; //220 WORD Reserved9; //221 WORD TransportMajorVersionNumber; //222 WORD TransportMinorVersionNumber; //223 WORD ReservedForCeAta2[10]; //224-233 WORD MinimumBlocksPerDownloadMicrocode; //234 WORD MaximumBlocksPerDownloadMicrocode; //235 WORD Reserved10[19]; //236-254 WORD IntegrityWord; //255 }ATA_IDENTIFY_DEVICE ; typedef struct NVME_IDENTIFY_DEVICE { CHAR Reserved1[4]; CHAR SerialNumber[20]; CHAR Model[40]; CHAR FirmwareRev[8]; CHAR Reserved2[9]; CHAR MinorVersion; SHORT MajorVersion; CHAR Reserved3[428]; }NVME_IDENTIFY_DEVICE; union IDENTIFY_DEVICE { ATA_IDENTIFY_DEVICE A; NVME_IDENTIFY_DEVICE N; }; typedef struct _SMART_ATTRIBUTE //smart属性 { BYTE Id; WORD StatusFlags; BYTE CurrentValue; BYTE WorstValue; BYTE RawValue[6]; BYTE Reserved; } SMART_ATTRIBUTE; typedef struct ATA_SMART_INFO { IDENTIFY_DEVICE identifydevice; SMART_ATTRIBUTE Attribute[MAX_ATTRIBUTE]; BYTE SmartReadData[512]; }ATA_SMART_INFO; #pragma pack ()
#include "h.h" void capacity(char* model_buf, char* sn_buf, char* fw_buf) { WORD count = 0; DWORD dw ; DWORD dwSize = MAX_PATH; DWORD driver = 0; char szLogicalDrives[MAX_PATH] = {0}; //缓冲区 DWORD dwResult = GetLogicalDriveStrings(dwSize,szLogicalDrives); //获取逻辑驱动器号字符串 //获取驱动器数 dw = GetLogicalDrives(); while( dw != 0 ) { if((dw&1) != 0) { count++; } dw>>=1; } printf("驱动器个数:%d ",count); printf("------------------------------ "); //处理获取到的结果 if (dwResult > 0 && dwResult <= MAX_PATH) { char* szSingleDrive = szLogicalDrives; //从缓冲区起始地址开始 while(*szSingleDrive) { printf("Drive: %s ", szSingleDrive); //输出单个驱动器的驱动器号 printf(" "); GetDisksmart(count,driver, model_buf, sn_buf, fw_buf); Getsmart(driver); driver++; // 获取下一个驱动器号起始地址 szSingleDrive += strlen(szSingleDrive) + 1; } } }
#include "h.h" const WORD IDE_ATAPI_IDENTIFY = 0xA1; // 读取ATAPI设备的命令 const WORD IDE_ATA_IDENTIFY = 0xEC; // 读取ATA设备的命令 const int DISK_PATH_LEN = 128; const int DISK_INFO_BUF_LEN = 128; void ChangeByteOrder(PCHAR szString, USHORT uscStrSize) { USHORT i; CHAR temp; for (i = 0; i < uscStrSize; i+=2) { temp = szString[i]; szString[i] = szString[i+1]; szString[i+1] = temp; } } void GetDisksmart(WORD count,DWORD driver, CHAR *modelNumber, CHAR *sn_buf, CHAR * fw_buf ) { // CHAR sFilePath[DISK_PATH_LEN] ; BOOL result; // results flag DWORD readed; // discard results HANDLE hDevice; char sFilePath[255] ; while(driver!=count){ //循环 sprintf(sFilePath, "\\\\.\\PhysicalDrive%d", driver); hDevice = CreateFile( sFilePath, // drive to open GENERIC_READ | GENERIC_WRITE,// GENERIC_READ|GENERIC_WRITE , // access to the drive FILE_SHARE_READ| FILE_SHARE_WRITE , //share mode NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL // do not copy file attribute ); if (hDevice == INVALID_HANDLE_VALUE) { printf("无法识别序列号等信息"); //printf("------------------------------ "); break; //fprintf(stderr, "CreateFile() Error: %ld ", GetLastError()); // return (DWORD)-1; } GETVERSIONINPARAMS gvopVersionParams; result = DeviceIoControl( hDevice, SMART_GET_VERSION, //控制码 NULL, 0, &gvopVersionParams, // 输出数据缓冲区指针 sizeof(gvopVersionParams), // 输出数据缓冲区指针长度 &readed, // 输出数据实际长度单元长度 NULL); if (!result) //fail { printf("无法识别序列号等信息 "); //printf("------------------------------ "); break; // fprintf(stderr, "SMART_GET_VERSION Error: %ld ", GetLastError()); // (void)CloseHandle(hDevice); // return (DWORD)-1; } if(0 == gvopVersionParams.bIDEDeviceMap) { printf("无法识别序列号等信息 "); //printf("------------------------------ "); break; //return (DWORD)-1; } // IDE or ATAPI IDENTIFY cmd BYTE btIDCmd; SENDCMDINPARAMS inParams; // IDE设备IOCTL输入数据结构 BYTE nDrive =0; btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; // 输出 structure BYTE outParams[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1]; // + 512 - 1 //fill in the input buffer inParams.cBufferSize = 0; // 缓冲区字节数 //or IDENTIFY_BUFFER_SIZE ? inParams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES; // irDriveRegs :IDE寄存器组 inParams.irDriveRegs.bSectorCountReg = 1; inParams.irDriveRegs.bSectorNumberReg = 1; inParams.irDriveRegs.bCylLowReg = 0; inParams.irDriveRegs.bCylHighReg = 0; inParams.irDriveRegs.bDriveHeadReg = (nDrive & 1) ? 0xB0 : 0xA0; inParams.irDriveRegs.bCommandReg = btIDCmd; //inParams.bDriveNumber = nDrive; //get the attributes result = DeviceIoControl( hDevice, SMART_RCV_DRIVE_DATA, &inParams, sizeof(SENDCMDINPARAMS) - 1, outParams, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, &readed, NULL); if (!result) //获取失败 { printf("无法识别序列号等信息 "); break; //fprintf(stderr, "SMART_RCV_DRIVE_DATA Error: %ld ", GetLastError()); //(void)CloseHandle(hDevice); // return (DWORD)-1; } (void)CloseHandle(hDevice); ATA_IDENTIFY_DEVICE * ip = (ATA_IDENTIFY_DEVICE *)((SENDCMDOUTPARAMS*)outParams)->bBuffer ; //ip指向获取的硬盘信息 // 固件 memset(fw_buf, 0, 8); memcpy(fw_buf, ip->FirmwareRev, 8); fw_buf[8] = ‘