type2
#include <vector>
const DWORD Signature = 'RSMB';
DWORD needBufferSize = 0;
CString str;
typedef struct RawSMBIOSData {
BYTE Used20CallingMethod;
BYTE SMBIOSMajorVersion; //SMBIOS主要版本
BYTE SMBIOSMinorVersion; //SMBIOS小版本
BYTE DmiRevision; //DMI修订
DWORD Length; //SMBIOS表总长度
BYTE SMBIOSTableData[]; //SMBIOS表数据
};
//SMBIOS表 Type=2时的结构
typedef struct _TYPE_2_ {
BYTE Type; //表的Type
BYTE Length; //表字节数
WORD Handle;
BYTE Manufacturer; //制造商名字索引
BYTE Product; // 产品字符串索引
BYTE Version; // 版本字符串索引
BYTE SerialNumber; // 序列号字符串索引
BYTE AssetTag;
BYTE FeatureFlags;
BYTE LocationInChassis;
BYTE ChassisHandle;
BYTE Type1;
BYTE NumObjHandle;
WORD* pObjHandle;
} BoardInfo, * PBoardInfo;
#pragma pack(pop)
void Csebei2Dlg::OnBnClickedButton1()
{
needBufferSize = GetSystemFirmwareTable(Signature, 0, NULL, 0);//获取系统固件表空间大小
//【参数3和参数4为NULL和0,只是为了返回真实大小】
//【1540】
if (needBufferSize == 0)
{
str.Format(_T("无法获取缓冲区大小。错误代码:%d\n"), GetLastError());
OutputDebugString(str);
return;
}
std::vector<BYTE> pBuffer(needBufferSize);//分配所需的缓冲区
needBufferSize = GetSystemFirmwareTable(Signature, 0, pBuffer.data(), needBufferSize);//获取系统固件表
if (needBufferSize == 0)
{
str.Format(_T("无法获取系统固件表。错误代码:%d\n"), GetLastError());
OutputDebugString(str);
return;
}
RawSMBIOSData* pRawSMBIOSData = reinterpret_cast<RawSMBIOSData*>(pBuffer.data());//将缓冲区转换为RawSMBIOSData指针
// ********遍历SMBIOS表,寻找类型为2的表**************
BYTE* pCurrent = pRawSMBIOSData->SMBIOSTableData;//当前位置
BYTE* pEnd = pCurrent + pRawSMBIOSData->Length;
while (pCurrent < pEnd) {
// 获取当前表的类型和大小
BoardInfo* type2 = reinterpret_cast<BoardInfo*>(pCurrent);
// 检查是否为类型2
if (type2->Type == 2) { //
AfxMessageBox(_T("type=2"));
break;
}
// 跳过当前表的大小和字符串表
pCurrent += type2->Length;; //修改当前位置
while ((*pCurrent | *(pCurrent + 1)) != 0)
pCurrent++;//【个人:跳过每个表末尾的\0】
// 跳过两个NULL字符,以到达下一个表
pCurrent += 2;//【个人:跳过每个表的间隔NULL字符】
}
}
我的问题:请不要使用GPT回答,GPT我已经使用,不正确,所以请人工测试正确后再回答
上面代码我已经找到SMBIOS表当type=2时的表,如何读出其中的序列号 ?
根据您提供的代码,当找到SMBIOS表中的类型为2的表时,可以通过以下方式读取其中的序列号:
1. 首先,找到类型为2的表后,可以使用type2指针指向该表的内存位置:
BoardInfo* type2 = reinterpret_cast<BoardInfo*>(pCurrent);
2. 再通过type2->SerialNumber即可获取序列号字符串索引。假设序列号索引为SerialNumberIndex。
3. 若要获取序列号字符串,需要从SMBIOS主体数据块(pRawSMBIOSData->SMBIOSTableData)中的字符串表开始位置查找对应的字符串。
4. 遍历字符串表,直到找到序列号字符串索引对应的位置,然后通过相对索引偏移量找到序列号字符串的位置:
BYTE* pStringTable = pRawSMBIOSData->SMBIOSTableData + pRawSMBIOSData->Length;
BYTE* pSerialNumber = pStringTable;
for (int i = 1; i < type2->SerialNumber; i++) {
while (*pSerialNumber != '\0')
pSerialNumber++;
pSerialNumber++; // 跳过'\0'
}
5. 最后,可以将序列号字符串保存在一个CString对象中:
CString serialNumber(reinterpret_cast<char*>(pSerialNumber));
请注意,以上代码片段仅供参考,具体实现可能需要根据您系统的具体情况进行调整。建议根据实际测试结果进行调试和修改。
球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}
要读取SMBIOS表中类型为2的表中的序列号,可以按照以下步骤进行:
1. 在找到类型为2的表后,通过type2指针可以访问到该表的各个字段。
2. 序列号字段在类型为2的表中的索引是SerialNumber,可以通过type2->SerialNumber来获取该字段的索引值。
3. 通过索引值,可以在SMBIOS表数据中找到序列号字段的位置。根据SMBIOS规范,字符串表是以NULL字符('\0')分隔的,所以可以通过遍历字符串表来找到序列号字段所在的位置。
4. 在找到序列号字段的位置后,可以读取该字段的值。根据SMBIOS规范,序列号字段是以NULL字符('\0')结尾的,所以可以通过读取连续的字符直到遇到NULL字符来获取序列号的值。
下面是修改后的代码示例,演示了如何读取SMBIOS表中类型为2的表中的序列号:
void Csebei2Dlg::OnBnClickedButton1()
{
// ...
while (pCurrent < pEnd) {
BoardInfo* type2 = reinterpret_cast<BoardInfo*>(pCurrent);
if (type2->Type == 2) {
// 读取序列号字段
BYTE* pSerialNumber = pCurrent + offsetof(BoardInfo, SerialNumber);
BYTE serialNumberIndex = *pSerialNumber;
// 查找序列号字段的位置
BYTE* pStringTable = pCurrent + type2->Length;
BYTE* pSerialNumberField = pStringTable;
for (int i = 1; i < serialNumberIndex; i++) {
while (*pSerialNumberField != '\0') {
pSerialNumberField++;
}
pSerialNumberField++;
}
// 读取序列号的值
CString serialNumber = reinterpret_cast<char*>(pSerialNumberField);
// 输出序列号
str.Format(_T("序列号:%s\n"), serialNumber);
OutputDebugString(str);
break;
}
// ...
}
// ...
}
在上述代码中,我们首先通过type2->SerialNumber获取序列号字段的索引值,然后在字符串表中查找该字段的位置。最后,通过reinterpret_cast将该位置的字节指针转换为char*指针,并将其作为CString类型输出。请注意,这里假设序列号字段是以ASCII字符编码的字符串。如果序列号字段采用其他编码方式,需要相应地进行转换处理。 Mike_python小 发表于 2023-9-28 07:06
根据您提供的代码,当找到SMBIOS表中的类型为2的表时,可以通过以下方式读取其中的序列号:
1. 首先,找到 ...
请测试一下,没有返回序列号? lm68140318 发表于 2023-9-28 08:19
请测试一下,没有返回序列号?
// 跳过当前表的大小和字符串表
pCurrent += type2->Length;; //修改当前位置
while ((*pCurrent | *(pCurrent + 1)) != 0)
pCurrent++;//【个人:跳过每个表末尾的\0】
// 跳过两个NULL字符,以到达下一个表
pCurrent += 2;//【个人:跳过每个表的间隔NULL字符】
这几行代码是你写的,你真的理解这几行代码在做什么吗?
这几行代码在跳过格式区域后面的那个字符串区域
这是在跳字符串,你想要的那个序列号也是字符串,就在这里
你跳的时候数一数,跳到你想要的那个字符串的时候就停下来,就是这样
我这边的这个SN对应的字符串是 Default string
这是全部的6个字符串
(gdb) print *board
$1 = {Header = {Type = 2 '\002', Length = 15 '\017', Handle = 2}, Manufacturer = 1 '\001', Product = 2 '\002', Version = 3 '\003', SN = 4 '\004',
AssetTag = 5 '\005', FeatureFlags = 9 '\t', LocationInChassis = 6 '\006', ChassisHandle = 3, Type = 10 '\n', NumObjHandle = 0 '\000',
pObjHandle = 0x6574796261676947}
Gigabyte Technology Co., Ltd.
Z790 UD
x.x
Default string
Default string
Default string
还有,要学着调试程序么,程序是调试出来的
#include <stdio.h>
#include <windows.h>
typedef struct RawSMBIOSData
{
BYTE Used20CallingMethod;
BYTE SMBIOSMajorVersion;
BYTE SMBIOSMinorVersion;
BYTE DmiRevision;
DWORD Length;
BYTE SMBIOSTableData[];
} __attribute__((packed)) RawSMBIOSData;
typedef struct {
BYTE Type;
BYTE Length;
WORD Handle;
} __attribute__((packed)) SMBIOSHEADER;
typedef struct {
SMBIOSHEADER Header;
UCHAR Manufacturer;
UCHAR Product;
UCHAR Version;
UCHAR SN;
UCHAR AssetTag;
UCHAR FeatureFlags;
UCHAR LocationInChassis;
UINT16ChassisHandle;
UCHAR Type;
UCHAR NumObjHandle;
UINT16*pObjHandle;
} __attribute__((packed)) BoardInfo;
int main(void) {
DWORD signature = 0x52534d42; // 'RSMB'
UINT size = GetSystemFirmwareTable(signature, 0, NULL, 0);
if(!size) return -1;
BYTE buff;
GetSystemFirmwareTable(signature, 0, buff, size);
RawSMBIOSData *smbios = (RawSMBIOSData *)buff;
BoardInfo *board = NULL;
BYTE *current = smbios->SMBIOSTableData;
while(current < &smbios->SMBIOSTableData) {
SMBIOSHEADER *header = (SMBIOSHEADER *)current;
if(header->Type == 2) {
board = (BoardInfo *)current; break;
}
current += header->Length;
while(*current || *(current + 1)) ++current;
current += 2;
}
current = (BYTE *)board + board->Header.Length;
BYTE *str = NULL;
DWORD index = board->SN;
DWORD count = 0;
/*
while(*current) {
while(*current) {putchar(*current); ++current;}
putchar('\n');
++count;
if(!*(current + 1)) break;
++current;
}
*/
while(*current) {
++count; if(count == index) { // 索引是从1开始的,这神奇的设计,对吧?
str = current;
}
while(*current) ++current;
if(!*(current + 1)) break;
++current;
}
if(str) printf("%s\n", str);
return 0;
}
页:
[1]