⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartreader.cpp

📁 源码演示了如何读取S.M.A.R.T硬盘信息的方法
💻 CPP
字号:
// SmartReader.cpp: implementation of the CSmartReader class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SMART.h"
#include "SmartReader.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define DRIVE_HEAD_REG	0xA0

CSmartReader::CSmartReader()
{
	InitAll();
	FillAttribGenericDetails();
}

CSmartReader::~CSmartReader()
{
	CloseAll();
}

VOID CSmartReader::InitAll()
{
	m_ucDrivesWithInfo=m_ucDrives=0;
	m_oSmartInfo.clear();
}

VOID CSmartReader::CloseAll()
{
	InitAll();
}

BOOL CSmartReader::ReadSMARTValuesForAllDrives()
{
	DWORD dwBits,dwBitVal;
	BOOL bFlag=0;
	char szDrv[MAX_PATH]={0};
	BYTE ucDriveIndex=0,ucT2=0;

	CloseAll();
	dwBits=GetLogicalDrives();
	dwBitVal=1;ucT2=0;
	bFlag=(dwBits & dwBitVal);
	while(ucT2<32)
	{
		if(bFlag)
		{
			wsprintf(szDrv,"%c:\\",'A'+ucT2);
			switch(GetDriveType(szDrv))
			{
				case DRIVE_FIXED:
						ucDriveIndex=ucT2-2;
						if(ReadSMARTInfo(ucDriveIndex))
							m_ucDrivesWithInfo++;
						m_ucDrives++;
					break;

				default:
					
					break;
			}
		}
		dwBitVal=dwBitVal*2;
		bFlag=(dwBits & dwBitVal);
		++ucT2;
	}
	if(m_ucDrives==m_ucDrivesWithInfo)
		return TRUE;
	else
		return FALSE;
}

BOOL CSmartReader::ReadSMARTInfo(BYTE ucDriveIndex)
{
	HANDLE hDevice=NULL;
	char szT1[MAX_PATH]={0};
	BOOL bRet=FALSE;
	DWORD dwRet=0;
	
	wsprintf(szT1,"\\\\.\\PHYSICALDRIVE%d",ucDriveIndex);
	hDevice=CreateFile(szT1,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM,NULL);
	if(hDevice!=INVALID_HANDLE_VALUE)
	{
		bRet=DeviceIoControl(hDevice,SMART_GET_VERSION,NULL,0,&m_stDrivesInfo[ucDriveIndex].m_stGVIP,sizeof(GETVERSIONINPARAMS),&dwRet,NULL);
		if(bRet)
		{			
			if((m_stDrivesInfo[ucDriveIndex].m_stGVIP.fCapabilities & CAP_SMART_CMD)==CAP_SMART_CMD)
			{
				if(IsSmartEnabled(hDevice,ucDriveIndex))
				{
					bRet=CollectDriveInfo(hDevice,ucDriveIndex);
					bRet=ReadSMARTAttributes(hDevice,ucDriveIndex);
				}
			}
		}
		CloseHandle(hDevice);
	}
	return bRet;
}

BOOL CSmartReader::IsSmartEnabled(HANDLE hDevice,UCHAR ucDriveIndex)
{
	SENDCMDINPARAMS stCIP={0};
	SENDCMDOUTPARAMS stCOP={0};
	DWORD dwRet=0;
	BOOL bRet=FALSE;

	stCIP.cBufferSize=0;
	stCIP.bDriveNumber =ucDriveIndex;
	stCIP.irDriveRegs.bFeaturesReg=ENABLE_SMART;
	stCIP.irDriveRegs.bSectorCountReg = 1;
	stCIP.irDriveRegs.bSectorNumberReg = 1;
	stCIP.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
	stCIP.irDriveRegs.bCylHighReg = SMART_CYL_HI;
	stCIP.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG;
	stCIP.irDriveRegs.bCommandReg = SMART_CMD;
	
	bRet=DeviceIoControl(hDevice,SMART_SEND_DRIVE_COMMAND,&stCIP,sizeof(stCIP),&stCOP,sizeof(stCOP),&dwRet,NULL);
	if(bRet)
	{

	}
	else
	{
		dwRet=GetLastError();
		m_stDrivesInfo[ucDriveIndex].m_csErrorString.Format("Error %d in reading SMART Enabled flag",dwRet);
	}
	return bRet;
}

BOOL CSmartReader::CollectDriveInfo(HANDLE hDevice,UCHAR ucDriveIndex)
{
	BOOL bRet=FALSE;
	SENDCMDINPARAMS stCIP={0};
	DWORD dwRet=0;
	#define OUT_BUFFER_SIZE IDENTIFY_BUFFER_SIZE+16
	char szOutput[OUT_BUFFER_SIZE]={0};

	stCIP.cBufferSize=IDENTIFY_BUFFER_SIZE;
	stCIP.bDriveNumber =ucDriveIndex;
	stCIP.irDriveRegs.bFeaturesReg=0;
	stCIP.irDriveRegs.bSectorCountReg = 1;
	stCIP.irDriveRegs.bSectorNumberReg = 1;
	stCIP.irDriveRegs.bCylLowReg = 0;
	stCIP.irDriveRegs.bCylHighReg = 0;
	stCIP.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG;
	stCIP.irDriveRegs.bCommandReg = ID_CMD;

	bRet=DeviceIoControl(hDevice,SMART_RCV_DRIVE_DATA,&stCIP,sizeof(stCIP),szOutput,OUT_BUFFER_SIZE,&dwRet,NULL);
	if(bRet)
	{
		CopyMemory(&m_stDrivesInfo[ucDriveIndex].m_stInfo,szOutput+16,sizeof(ST_IDSECTOR));
		ConvertString(m_stDrivesInfo[ucDriveIndex].m_stInfo.sModelNumber,39);
		ConvertString(m_stDrivesInfo[ucDriveIndex].m_stInfo.sSerialNumber,20);
		ConvertString(m_stDrivesInfo[ucDriveIndex].m_stInfo.sFirmwareRev,8);
	}
	else
		dwRet=GetLastError();
	return bRet;
}

VOID CSmartReader::ConvertString(PBYTE pString,DWORD cbData)
{
	CString csT1;
	char szT1[MAX_PATH]={0};
	for(int nC1=0;nC1<cbData;nC1+=2)
	{
		szT1[nC1]=pString[nC1+1];
		szT1[nC1+1]=pString[nC1];
	}
	csT1=szT1;csT1.TrimLeft();csT1.TrimRight();
	lstrcpy(szT1,(PCHAR)(LPCTSTR)csT1);
	memcpy(pString,szT1,cbData);
}

VOID CSmartReader::FillAttribGenericDetails()
{
	char szINIFileName[MAX_PATH]={0},szKeyName[MAX_PATH]={0},szValue[1024]={0};
	int nC1,nSmartAttribs;
	ST_SMART_DETAILS stSD;

	m_oSMARTDetails.clear();
//	if(IsDebuggerPresent()==FALSE)
	{
		GetModuleFileName(NULL,szINIFileName,MAX_PATH);
		szINIFileName[lstrlen(szINIFileName)-3]=0;
		lstrcat(szINIFileName,"ini");
	}
//	else
//		wsprintf(szINIFileName,"D:\\Saneesh\\Projects\\Helpers\\SMART\\Smart.ini");
	nSmartAttribs=GetPrivateProfileInt("General","Max Attributes",0,szINIFileName);
	for(nC1=0;nC1<nSmartAttribs;++nC1)
	{
		wsprintf(szKeyName,"Attrib%d",nC1);
		stSD.m_ucAttribId=GetPrivateProfileInt(szKeyName,"Id",0,szINIFileName);
		stSD.m_bCritical=GetPrivateProfileInt(szKeyName,"Critical",0,szINIFileName);
		GetPrivateProfileString(szKeyName,"Name","",szValue,1024,szINIFileName);
		stSD.m_csAttribName=szValue;
		GetPrivateProfileString(szKeyName,"Details","",szValue,1024,szINIFileName);
		stSD.m_csAttribDetails=szValue;
		m_oSMARTDetails.insert(SMARTDETAILSMAP::value_type(stSD.m_ucAttribId,stSD));
	}
}

ST_SMART_DETAILS *CSmartReader::GetSMARTDetails(BYTE ucAttribIndex)
{
	SMARTDETAILSMAP::iterator pIt;
	ST_SMART_DETAILS *pRet=NULL;

	pIt=m_oSMARTDetails.find(ucAttribIndex);
	if(pIt!=m_oSMARTDetails.end())
		pRet=&pIt->second;

	return pRet;
}

ST_SMART_INFO *CSmartReader::GetSMARTValue(BYTE ucDriveIndex,BYTE ucAttribIndex)
{
	SMARTINFOMAP::iterator pIt;
	ST_SMART_INFO *pRet=NULL;

	pIt=m_oSmartInfo.find(MAKELPARAM(ucAttribIndex,ucDriveIndex));
	if(pIt!=m_oSmartInfo.end())
		pRet=(ST_SMART_INFO *)pIt->second;
	return pRet;
}

BOOL CSmartReader::ReadSMARTAttributes(HANDLE hDevice,UCHAR ucDriveIndex)
{
	SENDCMDINPARAMS stCIP={0};
	DWORD dwRet=0;
	BOOL bRet=FALSE;
	BYTE	szAttributes[sizeof(ST_ATAOUTPARAM) + READ_ATTRIBUTE_BUFFER_SIZE - 1];
	UCHAR ucT1;
	PBYTE pT1,pT3;PDWORD pT2;
	ST_SMART_INFO *pSmartValues;

	stCIP.cBufferSize=READ_ATTRIBUTE_BUFFER_SIZE;
	stCIP.bDriveNumber =ucDriveIndex;
	stCIP.irDriveRegs.bFeaturesReg=READ_ATTRIBUTES;
	stCIP.irDriveRegs.bSectorCountReg = 1;
	stCIP.irDriveRegs.bSectorNumberReg = 1;
	stCIP.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
	stCIP.irDriveRegs.bCylHighReg = SMART_CYL_HI;
	stCIP.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG;
	stCIP.irDriveRegs.bCommandReg = SMART_CMD;
	bRet=DeviceIoControl(hDevice,SMART_RCV_DRIVE_DATA,&stCIP,sizeof(stCIP),szAttributes,sizeof(ST_ATAOUTPARAM) + READ_ATTRIBUTE_BUFFER_SIZE - 1,&dwRet,NULL);
	if(bRet)
	{
		m_stDrivesInfo[ucDriveIndex].m_ucSmartValues=0;
		m_stDrivesInfo[ucDriveIndex].m_ucDriveIndex=ucDriveIndex;
		pT1=(PBYTE)(((ST_ATAOUTPARAM*)szAttributes)->bBuffer);
		for(ucT1=0;ucT1<30;++ucT1)
		{
			pT3=&pT1[2+ucT1*12];
			pT2=(PDWORD)&pT3[INDEX_ATTRIB_RAW];
			pT3[INDEX_ATTRIB_RAW+2]=pT3[INDEX_ATTRIB_RAW+3]=pT3[INDEX_ATTRIB_RAW+4]=pT3[INDEX_ATTRIB_RAW+5]=pT3[INDEX_ATTRIB_RAW+6]=0;
			if(pT3[INDEX_ATTRIB_INDEX]!=0)
			{
				pSmartValues=&m_stDrivesInfo[ucDriveIndex].m_stSmartInfo[m_stDrivesInfo[ucDriveIndex].m_ucSmartValues];
				pSmartValues->m_ucAttribIndex=pT3[INDEX_ATTRIB_INDEX];
				pSmartValues->m_ucValue=pT3[INDEX_ATTRIB_VALUE];
				pSmartValues->m_ucWorst=pT3[INDEX_ATTRIB_WORST];
				pSmartValues->m_dwAttribValue=pT2[0];
				pSmartValues->m_dwThreshold=MAXDWORD;
				m_oSmartInfo[MAKELPARAM(pSmartValues->m_ucAttribIndex,ucDriveIndex)]=pSmartValues;
				m_stDrivesInfo[ucDriveIndex].m_ucSmartValues++;
			}
		}
	}
	else
		dwRet=GetLastError();

	stCIP.irDriveRegs.bFeaturesReg=READ_THRESHOLDS;
	stCIP.cBufferSize=READ_THRESHOLD_BUFFER_SIZE; // Is same as attrib size
	bRet=DeviceIoControl(hDevice,SMART_RCV_DRIVE_DATA,&stCIP,sizeof(stCIP),szAttributes,sizeof(ST_ATAOUTPARAM) + READ_ATTRIBUTE_BUFFER_SIZE - 1,&dwRet,NULL);
	if(bRet)
	{
		pT1=(PBYTE)(((ST_ATAOUTPARAM*)szAttributes)->bBuffer);
		for(ucT1=0;ucT1<30;++ucT1)
		{
			pT2=(PDWORD)&pT1[2+ucT1*12+5];
			pT3=&pT1[2+ucT1*12];
			pT3[INDEX_ATTRIB_RAW+2]=pT3[INDEX_ATTRIB_RAW+3]=pT3[INDEX_ATTRIB_RAW+4]=pT3[INDEX_ATTRIB_RAW+5]=pT3[INDEX_ATTRIB_RAW+6]=0;
			if(pT3[0]!=0)
			{
				pSmartValues=GetSMARTValue(ucDriveIndex,pT3[0]);
				if(pSmartValues)
					pSmartValues->m_dwThreshold=pT2[0];
			}
		}
	}
	return bRet;
}

ST_DRIVE_INFO *CSmartReader::GetDriveInfo(BYTE ucDriveIndex)
{
	return &m_stDrivesInfo[ucDriveIndex];
}
/*
		switch(pT3[0])
			{
				case SMART_ATTRIB_RAW_READ_ERROR_RATE:// Raw Read Error Rate
						TRACE("\n Raw Read Error Rate: %d",pT2[0]);
					break;

				case SMART_ATTRIB_SPIN_UP_TIME:// Spin up Time
						TRACE("\n Spin up Time:%d",pT2[0]);
					break;

				case SMART_ATTRIB_START_STOP_COUNT:// Start stop count
						TRACE("\n Start stop count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_START_REALLOCATION_SECTOR_COUNT:// Reallocation Sector Count
						TRACE("\n Reallocation Sector Count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_SEEK_ERROR_RATE:// Seek Error Rate
						TRACE("\n Seek Error Rate:%d",pT2[0]);
					break;

				case SMART_ATTRIB_POWER_ON_HOURS_COUNT:// Power On hours count
						TRACE("\n Power On hours count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_SPIN_RETRY_COUNT:// Spin retry count
						TRACE("\n Spin retry count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_DEVICE_POWER_CYCLE_COUNT:// Device Power cycle count
						TRACE("\n Device Power cycle count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_POWER_OFF_RETRACT_COUNT:// Power-off Retract Count
						TRACE("\n Power-off Retract Count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_LOAD_UNLOAD_CYCLE_COUNT:// Load/Unload cycle Count
						TRACE("\n Load/Unload cycle Count:%d",pT2[0]);
					break;

				case SMART_ATTRIB_TEMPERATURE: // Temperature
						TRACE("\n Temperature: %d C",pT2[0]);
					break;

				case SMART_ATTRIB_ECC_ON_THE_FLY_COUNT:// ECC on the fly count
						TRACE("\n ECC on the fly count: %d",pT2[0]);
					break;

				case SMART_ATTRIB_REALLOCATION_EVENT_COUNT:// Reallocation Event Count
						TRACE("\n Reallocation Event Count: %d",pT2[0]);
					break;

				case SMART_ATTRIB_CURRENT_PENDING_SECTOR_COUNT:// Current Pending Sector count
						TRACE("\n Current Pending Sector count: %d",pT2[0]);
					break;

				case SMART_ATTRIB_UNCORRECTABLE_SECTOR_COUNT:// Uncorrectable sector count
						TRACE("\n Uncorrectable sector count: %d",pT2[0]);
					break;

				case SMART_ATTRIB_ULTRA_DMA_CRC_ERROR_COUNT:// Ultra DMA CRC Error count
						TRACE("\n Ultra DMA CRC Error count: %d",pT2[0]);
					break;

				case SMART_ATTRIB_WRITE_ERROR_RATE://Write Error rate
						TRACE("\n Write Error rate: %d",pT2[0]);
					break;

				case SMART_ATTRIB_TA_COUNTER_INCREASED:// TA Counter increased
						TRACE("\n TA Counter increased: %d",pT2[0]);
					break;

				default:
						if(pT3[0]!=0)
						{
							TRACE("\n ID %d Value %d",pT3[0],pT2[0]);
						}
						else
							m_stDrivesInfo[ucDriveIndex].m_ucSmartValues--;
					break;
			}

*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -