This repository has been archived by the owner on Jan 6, 2020. It is now read-only.
forked from cavaliercoder/sysinv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
smbios.cpp
executable file
·194 lines (148 loc) · 4.27 KB
/
smbios.cpp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include "stdafx.h"
#include "sysinv.h"
#include "smbios.h"
/*
* See http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.8.0.pdf
*/
PNODE GetMemoryControllerDetail(PSMBIOS_STRUCT_HEADER header);
PNODE GetOemStringsDetail(PSMBIOS_STRUCT_HEADER header);
PRAW_SMBIOS_DATA smbios = NULL;
PRAW_SMBIOS_DATA GetSmbiosData()
{
DWORD bufferSize = 0;
if (NULL != smbios)
return smbios;
// Get required buffer size
bufferSize = GetSystemFirmwareTable('RSMB', 0, NULL, 0);
if (bufferSize) {
smbios = (PRAW_SMBIOS_DATA)LocalAlloc(LPTR, bufferSize);
bufferSize = GetSystemFirmwareTable('RSMB', 0, (PVOID)smbios, bufferSize);
}
return smbios;
}
void ReleaseSmbiosData()
{
if (NULL != smbios) {
LocalFree(smbios);
smbios = NULL;
}
}
PSMBIOS_STRUCT_HEADER GetNextStructure(PSMBIOS_STRUCT_HEADER previous)
{
PSMBIOS_STRUCT_HEADER next = NULL;
PBYTE c = NULL;
// Init SMBIOS data
if (NULL == smbios)
smbios = GetSmbiosData();
// Return NULL is no data found
if (NULL == smbios)
return NULL;
// Return first table if previous was NULL
if (NULL == previous)
return (PSMBIOS_STRUCT_HEADER)(&smbios->SMBIOSTableData[0]);
// Move to the end of the formatted structure
c = ((PBYTE)previous) + previous->Length;
// Search for the end of the unformatted structure (\0\0)
while (true) {
if ('\0' == *c && '\0' == *(c + 1)) {
/* Make sure next table is not beyond end of SMBIOS data
* (Thankyou Microsoft for ommitting the structure count
* in GetSystemFirmwareTable
*/
if ((c + 2) < ((PBYTE)smbios->SMBIOSTableData + smbios->Length))
return (PSMBIOS_STRUCT_HEADER)(c + 2);
else
return NULL; // We reached the end
}
c++;
}
return NULL;
}
PSMBIOS_STRUCT_HEADER GetNextStructureOfType(PSMBIOS_STRUCT_HEADER previous, DWORD type)
{
PSMBIOS_STRUCT_HEADER next = previous;
while (NULL != (next = GetNextStructure(next))) {
if (type == next->Type)
return next;
}
return NULL;
}
PSMBIOS_STRUCT_HEADER GetStructureByHandle(WORD handle)
{
PSMBIOS_STRUCT_HEADER header = NULL;
while (NULL != (header = GetNextStructure(header)))
if (handle == header->Handle)
return header;
return NULL;
}
LPTSTR GetSmbiosString(PSMBIOS_STRUCT_HEADER table, BYTE index)
{
DWORD i = 0;
DWORD len = 0;
LPTSTR unicode = _wcsdup(_T(""));
if (0 == index)
return unicode;
char *c = NULL;
for (i = 1, c = (char *)table + table->Length; '\0' != *c; c += strlen(c) + 1, i++) {
if (i == index) {
LocalFree(unicode);
len = MultiByteToWideChar(CP_UTF8, 0, c, -1, NULL, 0);
unicode = (LPTSTR)LocalAlloc(LPTR, sizeof(WCHAR)* len);
MultiByteToWideChar(CP_UTF8, 0, c, -1, unicode, len);
break;
}
}
return unicode;
}
PNODE GetSmbiosDetail()
{
PNODE biosNode = NULL;
PNODE node = NULL;
DWORD i = 0;
PSMBIOS_STRUCT_HEADER header = NULL;
LPTSTR unicode = NULL;
TCHAR buffer[MAX_PATH + 1];
GetSmbiosData();
// Create a node
biosNode = node_alloc(_T("Smbios"), 0);
swprintf(buffer, _T("%u.%u"), smbios->SMBIOSMajorVersion, smbios->SMBIOSMinorVersion);
node_att_set(biosNode, _T("Version"), buffer, 0);
swprintf(buffer, _T("%u"), smbios->DmiRevision);
node_att_set(biosNode, _T("DmiRevision"), buffer, NAFLG_FMT_NUMERIC);
done:
return biosNode;
}
// Type 5
PNODE GetMemoryControllerDetail(PSMBIOS_STRUCT_HEADER header)
{
return NULL;
}
// Type 11
PNODE EnumOemStrings()
{
PNODE node = NULL;
PNODE stringNode = NULL;
PRAW_SMBIOS_DATA smbios = GetSmbiosData();
PSMBIOS_STRUCT_HEADER header = NULL;
PBYTE cursor = NULL;
LPTSTR unicode = NULL;
TCHAR buffer[64];
DWORD i;
header = GetNextStructureOfType(header, SMB_TABLE_OEM_STRINGS);
if (NULL == header)
return node;
node = node_alloc(_T("OemStrings"), NFLG_TABLE);
cursor = (PBYTE)header;
// 0x04 Count
for (i = 1; i < *(cursor + 0x04); i++) {
// String index
_snwprintf(buffer, 64, _T("%u"), i);
unicode = GetSmbiosString(header, i);
// String value
stringNode = node_append_new(node, _T("OemString"), NFLG_TABLE_ROW);
node_att_set(stringNode, _T("Index"), buffer, NAFLG_FMT_NUMERIC);
node_att_set(stringNode, _T("Value"), unicode, 0);
LocalFree(unicode);
}
return node;
}