From 36ce07093b68b07513149577c209ae7a57ab356b Mon Sep 17 00:00:00 2001
From: Gabriele Contini <contini.mailing@gmail.com>
Date: 周日, 15 3月 2020 16:26:21 +0800
Subject: [PATCH] Merge branch 'feature/pc_identifiers' into develop issues #2 #3 #14 #49

---
 src/library/os/windows/isvm/BIOSReader.cpp |  121 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/src/library/os/windows/isvm/BIOSReader.cpp b/src/library/os/windows/isvm/BIOSReader.cpp
new file mode 100644
index 0000000..3300964
--- /dev/null
+++ b/src/library/os/windows/isvm/BIOSReader.cpp
@@ -0,0 +1,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;
+}

--
Gitblit v1.9.1