將以下程式碼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; };
執行畫面
參考資料: