SMBIOS读取本机的MEMORY信息

SMBIOS读取本机的MEMORY信息

示例

用Visual Studio 编写一个控制台程序,功能如下:
一、使用SMBIOS读取本机的MEMORY信息,并打印一下信息
[MEMORY]
NUM = 2
SIZE=32GB
[0]
LOCATOR=DIMM1
SIZE=16GB
TYPE=DDR4
SPEED=2666MHZ
MANUFACTURER=Micron
[1]
LOCATOR=DIMM1
SIZE=16GB
TYPE=DDR4
SPEED=2666MHZ
MANUFACTURER=Micron

代码

分别定义结构体存储SMBIOS信息的长度和尾部地址、type的三类信息(type、length、handle)、type16信息、type17信息。

SMBIOS开发文档

getMemery.cpp


// GetMemory.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


#pragma once //只编译一次,节省时间
/*包含的头文件*/
#include<stdio.h>
#include<string>
#include<iostream>
#include<windows.h>
#include <SDKDDKVer.h>
#include <tchar.h>
/*使用命名空间*/
using namespace std;
//保存之前的结构体对齐方式
#pragma pack(push) 
//使用新的结构体对齐方式
#pragma pack(1)

/*存储SMBIOS信息的长度和尾部地址*/
typedef struct _RawSMBIOSData
{
    DWORD Length;
    PBYTE* SMBIOSTableData;
} RawSMBIOSData, * PRawSMBIOSData;


/*存储各TYPE的三类信息*/
typedef struct _SMBIOSHEADER_
{
    BYTE Type;
    BYTE Length;
    WORD Handle;
} SMBIOSHEADER, * PSMBIOSHEADER;


/*存储TYPE16信息*/
typedef struct _TYPE_16_ {
    SMBIOSHEADER Header;
    UCHAR  Location;
    UCHAR  Use;
    UCHAR  MemoryErrorCorrection;
    ULONG32  MaximumCapacity;
    UINT16 MemoryErrorHandle;
    UINT16 NumberofMemoryDevices;
    ULONG32 ExtendedMaximumCapacity;
} PhysicalMemoryArray, * PPhysicalMemoryArray;

/*存储TYPE17信息*/
typedef struct _TYPE_17_ {
    SMBIOSHEADER Header;
    UINT16  PhysicalArrayHandle;
    UINT16  ErrorInformationHandle;
    UINT16  TotalWidth;
    UINT16  DataWidth;
    UINT16  Size;
    UCHAR   FormFactor;
    UCHAR   DeviceSet;
    UCHAR   DeviceLocator;
    UCHAR   BankLocator;
    UCHAR   MemoryType;
    UINT16  TypeDetail;
    UINT16  Speed;
    UCHAR   Manufacturer;
    UCHAR   SN;
    UCHAR   AssetTag;
    UCHAR   PN;
    UCHAR   Attributes;
} MemoryDevice, * PMemoryDevice;

enum _MemoryType_
{
    Other = 1, Un_known, DRAM, EDRAM,
    VRAM, SRAM, RAM, ROM, FLASH,
    EEPROM, FEPROM, EPROM, CDRAM,
    RAM_3D, SDRAM, SGRAM, RDRAM,
    DDR, DDR2, DDR2_FB_DIMM, Reserved_1,
    Reserved_2, Reserved_3, DDR3, FBD2, DDR4,
    LPDDR, LPDDR2, LPDDR3, LPDDR4,
    Logicalnonvolatiledevice, HBM, HBM2, DDR5, LPDDR5
};
//自定义对齐方式结束
#pragma pack(pop)
/*根据编码选择字符解析方式*/
#ifdef UNICODE
#define LocateString LocateStringW
#else
#define LocateString    LocateStringA
#endif

/*返回信息尾部地址*/
const char* toPointString(void* p)
{
    return (char*)p + ((PSMBIOSHEADER)p)->Length;
}

/*解析字符串*/
//获取MANUFACTURER(生产商)信息
const char* LocateStringA(const char* str, UINT i)
{
    static const char strNull[] = "Null String";

    if (0 == i || 0 == *str)
    {
        return strNull;
    }
    while (--i)
    {
        str += strlen((char*)str) + 1;
    }
    return str;
}

/*解析字符串*/
const wchar_t* LocateStringW(const char* str, UINT i)
{
    static wchar_t buff[2048];
    const char* pStr = LocateStringA(str, i);
    SecureZeroMemory(buff, sizeof(buff));
    MultiByteToWideChar(CP_OEMCP, 0, pStr, (int)strlen(pStr), buff, sizeof(buff));
    return buff;
}

/*输出TYPE16信息*/
bool ProcPhysicalMemoryArray(void* p)
{
    PPhysicalMemoryArray pMAMA = (PPhysicalMemoryArray)p;
    const char* str = toPointString(p);

    _tprintf(TEXT("NUM = %d\n"), pMAMA->NumberofMemoryDevices);    //Number of Memory Devices	内存设备数量
    _tprintf(TEXT("SIZE=%dGB\n"), pMAMA->MaximumCapacity / 1024 / 1024); //Maximum Capacity 最大容量
    return true;
}
/*输出TYPE17信息*/
bool ProcMemoryDevice(void* p)
{
    PMemoryDevice pMD = (PMemoryDevice)p;
    const char* str = toPointString(p);

    _tprintf(TEXT("LOCATOR=%s\n"), LocateString(str, pMD->DeviceLocator));
    _tprintf(TEXT("SIZE=%dGB\n"), pMD->Size / 1024);
    switch (pMD->MemoryType)
    {
    case Other:_tprintf(TEXT("TYPE=0x%02X Other\n"), pMD->MemoryType); break;    //X 表示以十六进制形式输出, 02 表示不足两位,前面补0输出
    case Un_known:_tprintf(TEXT("TYPE=0x%02X Unknown\n"), pMD->MemoryType); break;
    case DDR3:_tprintf(TEXT("TYPE=0x%02X DDR3\n"), pMD->MemoryType); break;        //DDR3是一种电脑内存规格
    case DDR4:_tprintf(TEXT("TYPE=0x%02X DDR4\n"), pMD->MemoryType); break;
    }
    if (pMD->Header.Length > 0x15)
    {
        _tprintf(TEXT("SPEED=%dMHZ\n"), pMD->Speed);  //时钟频率
        _tprintf(TEXT("MANUFACTURER=%s\n"), LocateString(str, pMD->Manufacturer)); //制造商
    }

    return true;
}

/*根据需求调用bool函数*/
bool DispatchStructType(PSMBIOSHEADER hdr)
{
    typedef struct {
        BYTE t;
        bool(*Proc)(void* p);
    } TPFUNC;

    const TPFUNC    tpfunc[] = {
        { 16, ProcPhysicalMemoryArray},
        { 17, ProcMemoryDevice },
    };

    for (UINT i = 0; i < sizeof(tpfunc) / sizeof(TPFUNC); i++)
    {
        if (tpfunc[i].t == hdr->Type)
        {
            tpfunc[i].Proc((void*)hdr);
            return true;
        }
    }

    return false;
}
/*选择要打印的SMBIOS信息*/
void DumpSMBIOSStruct(void* Addr, UINT Len)
{
    int i = 0;
    LPBYTE p = (LPBYTE)(Addr);
    const LPBYTE lastAddress = p + Len;
    PSMBIOSHEADER pHeader;
    for (;;)
    {
        pHeader = (PSMBIOSHEADER)p;
        if (pHeader->Type == 16)
        {
            _tprintf(TEXT("[Memory]\n"));
            DispatchStructType(pHeader);
            _tprintf(TEXT("\n"));
        }
        if (pHeader->Type == 17)
        {
            _tprintf(TEXT("[%d]\n"), i);
            i++;
            DispatchStructType(pHeader);
            _tprintf(TEXT("\n"));
        }
        if ((pHeader->Type == 127) && (pHeader->Length == 4))
        {
            break;
        }
        LPBYTE nt = p + pHeader->Length;
        while (0 != (*nt | *(nt + 1))) nt++;
        nt += 2;
        if (nt >= lastAddress)
            break;
        p = nt;
    }
}
void showhelp()
{
    cout << "SMBIOS读取本机的MEMORY信息!\n";
}

int _tmain(int argc, char* argv[])
{

    DWORD needBufferSize = 0;
    const BYTE byteSignature[] = { 'B','M','S','R' };
   /* 调用GetSystemFirmwareTable获取信息buffer大小

    DWORD iSignature = 'R';

    iSignature = iSignature << 8 | 'S';

    iSignature = iSignature << 8 | 'M';

    iSignature = iSignature << 8 | 'B';*/

    const DWORD Signature = *((DWORD*)byteSignature);
    LPBYTE pBuff = NULL;
    /*调用接口获取信息长度*/
    needBufferSize = GetSystemFirmwareTable(Signature, 0, NULL, 0);
    /*根据信息长度开辟内存空间*/
    pBuff = (LPBYTE)malloc(needBufferSize);
    if (pBuff)
    {
        //再次调用接口获取信息
        GetSystemFirmwareTable(Signature, 0, pBuff, needBufferSize);
        const PRawSMBIOSData pDMIData = (PRawSMBIOSData)pBuff;
        DumpSMBIOSStruct(&(pDMIData->SMBIOSTableData), pDMIData->Length);
    }
    showhelp();
}



结果

在这里插入图片描述
验证结果的过程,这里就不写了,大家各凭本事就查看。
创作不易,关注一下,不过分吧,源码和文档都放出来了,哈哈哈
最后希望你今天仍在起舞,不曾荒废。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值