Gabriele Contini
2020-02-24 9afdac17dcc8956fd795797bfc5b6e1c09285342
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "BIOSReader.h"
 
#include <cstdint>
 
#include "Native.h"
 
struct smbios_structure_header {
    uint8_t type;
    uint8_t length;
    uint16_t handle;
};
 
//
//    System information
//
struct smbios_type_1 {
    struct smbios_structure_header header;
    uint8_t manufacturer_str;
    uint8_t product_name_str;
    uint8_t version_str;
    uint8_t serial_number_str;
    uint8_t uuid[16];
    uint8_t wake_up_type;
    uint8_t sku_number_str;
    uint8_t family_str;
};
 
#define _TYPE_COUNT1 6
 
#define _CONCATE(x, y) x##y
#define CONCATE(x, y) _CONCATE(x, y)
#define TYPE_COUNT(t) CONCATE(_TYPE_COUNT, t)
 
//
//    Windows
//
#include <Windows.h>
#include <tchar.h>
 
int8_t *parse_smbiod_content(int8_t *addr, int8_t **indexes, int32_t *count) {
    //!    ignore 0
    int8_t parsed_count = 0;
    int8_t *raw_addr = addr;
 
    //!    first one
    if (indexes) *indexes = raw_addr;
 
    bool reach_terminal = false;
 
    while (true) {
        if (0 == *raw_addr++) {
            if (reach_terminal)
                break;
            else {
                ++parsed_count;
 
                if (count && parsed_count < *count) {
                    if (indexes) *(indexes + parsed_count) = raw_addr;
                }
 
                reach_terminal = true;
            }
        } else {
            reach_terminal = false;
            continue;
        }
    }
 
    if (count) *count = parsed_count;
 
    return raw_addr;
}
 
void read_smbios_type_1(int8_t *addr, SystemInformation *info) {
    smbios_type_1 *t1 = (smbios_type_1 *)addr;
 
    int32_t offset = ((0x0F) & (t1->header.length >> 4)) * 16 + (t1->header.length & 0x0F);
 
    int8_t *string_addr[TYPE_COUNT(1)] = {0};
 
    int32_t count = TYPE_COUNT(1);
    parse_smbiod_content((int8_t *)t1 + offset, string_addr, &count);
 
    if (0 != t1->manufacturer_str)
        info->Manufacturer = (std::string::traits_type::char_type *)string_addr[t1->manufacturer_str - 1];
 
    if (0 != t1->product_name_str)
        info->ProductName = (std::string::traits_type::char_type *)string_addr[t1->product_name_str - 1];
 
    if (0 != t1->serial_number_str)
        info->SerialNum = (std::string::traits_type::char_type *)string_addr[t1->serial_number_str - 1];
 
    if (0 != t1->version_str)
        info->SysVersion = (std::string::traits_type::char_type *)string_addr[t1->version_str - 1];
 
    if (0 != t1->family_str) info->family = (std::string::traits_type::char_type *)string_addr[t1->family_str - 1];
}
 
SystemInformation BIOSReader::readSystemInfo() {
    SystemInformation info;
 
    uint32_t size = 0;
    RawSMBIOSData *data = (RawSMBIOSData *)(LocateSMBIOS(&size));
 
    if (NULL == data || 0 == size) return info;
 
    smbios_structure_header *header = (smbios_structure_header *)(data->SMBIOSTableData);
 
    while (NULL != header) {
        if (1 == header->type) {
            read_smbios_type_1((int8_t *)header, &info);
            header = NULL;    //!    stop
        } else {
            int32_t offset = ((0x0F) & (header->length >> 4)) * 16 + (header->length & 0x0F);
            header = (smbios_structure_header *)parse_smbiod_content((int8_t *)header + offset, NULL, NULL);
        }
    }
 
    free(data);
    return info;
}