將以下程式碼Key到SMBIOS.cpp。
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
CSMBIOSClass cSMBIOS;
if(!cSMBIOS.InitSMBIOS())
{
printf("ERROR : initialize SMBIOS fail.\n");
return FALSE;
}
cSMBIOS.ScanSMBIOS();
cSMBIOS.PrintSMBIOSALLType(atoi(argv[1]));
return TRUE;
}
將以下程式碼Key到SMBIOSClass.cpp。
// CSMBIOSClass
CSMBIOSClass::CSMBIOSClass()
{
m_nTable_Length = 0;
m_nTypeCount = 0;
m_ucpbuffer = new UCHAR [SMBIOS_BUFFER_SIZE];
ZeroMemory(&m_SMBIOSInfo, sizeof(m_SMBIOSInfo));
}
CSMBIOSClass::~CSMBIOSClass()
{
if (m_ucpbuffer != NULL)
delete [] m_ucpbuffer;
}
//取出每個Type的真正長度,請參考SMBOS官方網頁內容的spec https://www.dmtf.org/standards/smbios
UCHAR SMBIOS::GetRealLength()
{
UCHAR ucRealLength = 0;
UCHAR* ucpBegin = NULL;
UCHAR* ucpPos = NULL;
ucpBegin = (UCHAR*)this;
ucpPos = ucpBegin + ucLength;
for (;;)
{
//每個Type結尾為兩個0
if ((*ucpPos == 0) && (*(ucpPos+1) == 0))
{
ucpPos+=2;
break;
}
ucpPos++;
}
ucRealLength = ucpPos - ucpBegin;
return ucRealLength;
}
//使用GetSystemFirmwareTable取得系統SMBIOS table
BOOL CSMBIOSClass::InitSMBIOS()
{
UCHAR ucTempData[SMBIOS_BUFFER_SIZE];
PRawSMBIOSData pRawSMBiosData = NULL;
ZeroMemory(ucTempData, sizeof(ucTempData));
if(!GetSystemFirmwareTable('RSMB', NULL, ucTempData, SMBIOS_BUFFER_SIZE) )
return FALSE;
pRawSMBiosData = (PRawSMBIOSData)&ucTempData[0];
m_nTable_Length = pRawSMBiosData->usLength;
memcpy(m_ucpbuffer, (UCHAR * )pRawSMBiosData->ucSMBIOSTableData, SMBIOS_BUFFER_SIZE);
return TRUE;
}
//掃出SMBIOS table全部的Type
void CSMBIOSClass::ScanSMBIOS()
{
SMBIOS *pSMB;
USHORT usOffset;
int iCount;
int i, j;
j = 0;
for(i = 0 ; i < SMBIOS_TYPE_COUNT ; i++)
{
usOffset = 0;
iCount = 0;
m_SMBIOSInfo[j].nTypeCount = 0 ;
while(usOffset < m_nTable_Length) {
pSMB = (SMBIOS*) (m_ucpbuffer + usOffset);
if (pSMB->ucType == i){
m_SMBIOSInfo[j].dwAddress[iCount] = (DWORD)(m_ucpbuffer + usOffset);
m_SMBIOSInfo[j].nLength[iCount] = pSMB->GetRealLength();
iCount++;
}
usOffset += pSMB->GetRealLength();
}
if(iCount){
m_SMBIOSInfo[j].bIsExist = TRUE;
m_SMBIOSInfo[j].ucType = i;
m_SMBIOSInfo[j].nTypeCount = iCount;
j++;
}
}
m_nTypeCount = j;
}
//印出指定Type的內容
void CSMBIOSClass::PrintSMBIOSALLType(int nType)
{
int i, j, k;
UCHAR *cpPtr = NULL;
for(i = 0 ; i < m_nTypeCount ; i++)
{
if( m_SMBIOSInfo[i].ucType == nType)
{
for(j = 0 ; j < m_SMBIOSInfo[i].nTypeCount ; j++)
{
printf("SMBIS Type %d, 0x%02X\n", m_SMBIOSInfo[i].ucType, m_SMBIOSInfo[i].ucType);
cpPtr = (UCHAR *)m_SMBIOSInfo[i].dwAddress[j];
PrintData(cpPtr, m_SMBIOSInfo[i].nLength[j]);
}
}
}
}
//映出SMBIOS每個Type的內容
void CSMBIOSClass::PrintData(UCHAR * ucptr, int nLength)
{
int j, k, nRemainLength = 0, nCurrentLength = 0;
printf(" | ");
for(j = 0 ; j < 16; j++)
printf("%02X ", j);
printf(" ");
for(j = 0 ; j < 16; j++)
printf("%X", j);
printf("\n");
printf("-----------------------------------------------------------------------\n");
nRemainLength = nLength;
for(j = 0 ; j < nLength ; j+=16)
{
if(nRemainLength > 16)
nCurrentLength = 16;
else
nCurrentLength = nRemainLength;
printf("%02X | ", j);
for(k = 1 ; k <= nCurrentLength ; k++)
printf("%02X ", ucptr[j+k-1]);
printf(" ");
if(nRemainLength < 16)
SetXY(55);
for(k = 1 ; k <= nCurrentLength ; k++)
{
if((ucptr[j+k-1] <= 0x20) || (ucptr[j+k-1] > 0x7F))
printf(".");
else
printf("%c", ucptr[j+k-1]);
}
printf("\n");
nRemainLength -= 16;
}
printf("-----------------------------------------------------------------------\n\n");
}
//設定游標座標位置
void CSMBIOSClass::SetXY(int nCoordX)
{
CONSOLE_SCREEN_BUFFER_INFO scrInfo;
COORD coord;
int x, y;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&scrInfo);
x = scrInfo.dwCursorPosition.X ;
y = scrInfo.dwCursorPosition.Y ;
coord.X = nCoordX;
coord.Y = y;
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}
將以下程式碼Key到SMBIOSClass.h
// CSMBIOSClass
#define SMBIOS_TYPE_COUNT 256
#define SMBIOS_BUFFER_SIZE 0xFFFF
typedef struct _tagSYSTYPEINFO
{
BOOL bIsExist;
UCHAR ucType;
int nTypeCount;
int nLength[32];
DWORD dwAddress[32];
}SYSTYPEINFO, *PSYSTYPEINFO;
//請參考微軟官網https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms724379(v=vs.85).aspx 定義的結構
typedef struct tagRawSMBIOSData
{
UCHAR ucUsed20CallingMethod;
UCHAR ucSMBIOSMajorVersion;
UCHAR ucSMBIOSMinorVersion;
UCHAR ucmiRevision;
ULONG usLength;
UCHAR ucSMBIOSTableData[];
}RawSMBIOSData, *PRawSMBIOSData;
class SMBIOS
{
public:
UCHAR ucType;
UCHAR ucLength;
USHORT usHandle;
UCHAR GetRealLength();
};
class CSMBIOSClass : SMBIOS
{
public:
CSMBIOSClass();
virtual ~CSMBIOSClass();
BOOL InitSMBIOS();
void ScanSMBIOS();
void PrintSMBIOSALLType(int nType);
private:
void PrintData(UCHAR * ucptr, int nLength);
void SetXY(int nCoordX);
SYSTYPEINFO m_SMBIOSInfo[SMBIOS_TYPE_COUNT];
UCHAR * m_ucpbuffer;
int m_nTable_Length, m_nTypeCount;
};
執行畫面
參考資料:
