From f4e683fc6bd6ac76f9979f49d737588b6ddf16b0 Mon Sep 17 00:00:00 2001
From: gcontini <1121667+gcontini@users.noreply.github.com>
Date: 周六, 14 11月 2020 22:13:13 +0800
Subject: [PATCH] windows smbios

---
 src/library/os/windows/dmi_info.cpp |   93 +++++++++
 doc/other/CREDITS.md                |    5 
 src/inspector/inspector.cpp         |    4 
 src/library/os/dmi_info.hpp         |    5 
 src/library/os/windows/smbios.hpp   |  397 ++++++++++++++++++++++++++++++++++++++++++++
 test/library/os/dmi_info_test.cpp   |    4 
 src/library/os/CMakeLists.txt       |    2 
 doc/index.rst                       |    2 
 8 files changed, 495 insertions(+), 17 deletions(-)

diff --git a/doc/index.rst b/doc/index.rst
index 38aba77..e7b1c53 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -46,7 +46,7 @@
 *******************
 The software is made by 4 main sub-components:
 
-* `licensecc`    : the C++ library with a C api (the part you have to integrate in your software) with minimal (or no) external dependencies. This is the project you're currently looking at.
+* ``licensecc``    : the C++ library with a C api (the part you have to integrate in your software) with minimal (or no) external dependencies. This is the project you're currently looking at.
 * ``lccinspector`` : a license debugger to be sent to the final customer to diagnose licensing problems or for calculating the hardware id before issuing the license.
 * ``lccgen``       : a license generator (github project `lcc-license-generator`_ ) to initialize the library and generate the licenses.
 * ``examples``     : usage samples (github project `examples <https://github.com/open-license-manager/examples>`_ ).
diff --git a/doc/other/CREDITS.md b/doc/other/CREDITS.md
index 7ee3c93..21794f8 100644
--- a/doc/other/CREDITS.md
+++ b/doc/other/CREDITS.md
@@ -1,5 +1,5 @@
 # Credits 
-The following open source code has been used in OpenLicenseManager. 
+The following open source code has been used in licensecc. 
 Thanks to every one of the authors of such projects. Without you open license manager would never have been released.  
 
 ## [inja](https://github.com/pantor/inja)
@@ -9,11 +9,10 @@
 Copyright (c) 2013-2017 Niels Lohmann
 
 
-## [isVM](https://github.com/0of/isvm)
+## [hwid generation](https://github.com/789sdf987s/hwid_generation)
 Thanks for the great smbios parsing code. It saved me days.
 
 MIT License
-Copyright (c) 2015 Magnus
 
 
 ## [SimpleIni](https://github.com/brofield/simpleini)
diff --git a/src/inspector/inspector.cpp b/src/inspector/inspector.cpp
index c4283a1..7af061e 100644
--- a/src/inspector/inspector.cpp
+++ b/src/inspector/inspector.cpp
@@ -127,7 +127,9 @@
 	license::os::DmiInfo dmi_info;
 	cout << "Bios vendor      :" << dmi_info.bios_vendor() << endl;
 	cout << "Bios description :" << dmi_info.bios_description() << endl;
-	cout << "System vendor    :" << dmi_info.sys_vendor() << endl << endl;
+	cout << "System vendor    :" << dmi_info.sys_vendor() << endl;
+	cout << "Cpu Vendor (dmi) :" << dmi_info.cpu_manufacturer() << endl;
+	cout << "Cpu Cores  (dmi) :" << dmi_info.cpu_cores() << endl;
 	cout << "==================" << endl;
 	if (argc == 2) {
 		const string fname(argv[1]);
diff --git a/src/library/os/CMakeLists.txt b/src/library/os/CMakeLists.txt
index 732d076..ef19453 100644
--- a/src/library/os/CMakeLists.txt
+++ b/src/library/os/CMakeLists.txt
@@ -16,7 +16,6 @@
   	    openssl/signature_verifier.cpp 
         execution_environment_common.cpp 
         windows/execution_environment.cpp
-        windows/isvm/BIOSReader.cpp
   	    windows/os_win.cpp
   	    windows/network.cpp)
 	ENDIF(UNIX)
@@ -29,7 +28,6 @@
         windows/signature_verifier.cpp 
         execution_environment_common.cpp 
         windows/execution_environment.cpp
-        windows/isvm/BIOSReader.cpp
         windows/os_win.cpp
         windows/network.cpp)
 ENDIF(UNIX OR OPENSSL_FOUND)
diff --git a/src/library/os/dmi_info.hpp b/src/library/os/dmi_info.hpp
index 94c7a3c..7bdc77c 100644
--- a/src/library/os/dmi_info.hpp
+++ b/src/library/os/dmi_info.hpp
@@ -17,6 +17,8 @@
 	std::string m_sys_vendor;
 	std::string m_bios_vendor;
 	std::string m_bios_description;
+	std::string m_cpu_manufacturer;
+	unsigned int m_cpu_cores = 0;
 
 public:
 	DmiInfo();
@@ -24,6 +26,9 @@
 	const std::string& bios_vendor() const { return m_bios_vendor; };
 	const std::string& sys_vendor() const { return m_sys_vendor; };
 	const std::string& bios_description() const { return m_bios_description; };
+	// Only Windows
+	const std::string& cpu_manufacturer() const { return m_cpu_manufacturer; };
+	const unsigned int cpu_cores() const { return m_cpu_cores; };
 };
 
 }  // namespace os
diff --git a/src/library/os/windows/dmi_info.cpp b/src/library/os/windows/dmi_info.cpp
index 478b517..a88e76d 100644
--- a/src/library/os/windows/dmi_info.cpp
+++ b/src/library/os/windows/dmi_info.cpp
@@ -5,19 +5,98 @@
  *      Author: devel
  */
 
-#include "isvm/BIOSReader.h"
+#include "smbios.hpp"
 #include "../../base/string_utils.h"
 #include "../dmi_info.hpp"
 
 namespace license {
 namespace os {
+
+using namespace smbios;
+
+//#pragma pack()
+struct RawSMBIOSData {
+	BYTE Used20CallingMethod;
+	BYTE SMBIOSMajorVersion;
+	BYTE SMBIOSMinorVersion;
+	BYTE DmiRevision;
+	DWORD Length;
+	//BYTE SMBIOSTableData[1];
+};
+
+bool readSMBIOS(std::vector<uint8_t> &buffer) {
+	const DWORD tableSignature = ('R' << 24) | ('S' << 16) | ('M' << 8) | 'B';
+	bool can_read = false;
+	uint32_t size = GetSystemFirmwareTable(tableSignature, 0, NULL, 0);
+	if (size > 0) {
+		buffer.resize(size);
+		if (GetSystemFirmwareTable(tableSignature, 0, buffer.data(), size)
+				> 0) {
+			can_read = true;
+		}
+	}
+	return can_read;
+}
+
 DmiInfo::DmiInfo() {
-	
-		BIOSReader reader;
-		SystemInformation info = reader.readSystemInfo();
-		m_sys_vendor = toupper_copy(info.Manufacturer);
-		m_bios_vendor = toupper_copy(info.ProductName);
-		m_bios_description = toupper_copy(info.SysVersion) + toupper_copy(info.family);
+	std::vector<uint8_t> raw_smbios_data;
+	if (readSMBIOS(raw_smbios_data)) {
+		smbios::parser smbios_parser;
+		RawSMBIOSData *rawData = reinterpret_cast<RawSMBIOSData *>(raw_smbios_data.data());
+		size_t length = static_cast<size_t>(rawData->Length);
+		uint8_t* buff= raw_smbios_data.data() + sizeof(RawSMBIOSData);
+		smbios_parser.feed(buff, length);
+
+		for (auto &header : smbios_parser.headers) {
+			string_array_t strings;
+			parser::extract_strings(header, strings);
+
+			switch (header->type) {
+				case types::baseboard_info: {
+					auto *const x = reinterpret_cast<baseboard_info *>(header);
+
+					if (x->length == 0) break;
+					if (x->manufacturer_name > 0 && x->manufacturer_name < x->length) {
+						m_sys_vendor = strings[x->manufacturer_name];
+					}
+				} break;
+
+				case types::bios_info: {
+					auto *const x = reinterpret_cast<bios_info *>(header);
+					if (x->length == 0) break;
+					if (x->vendor > 0 && x->vendor < x->length) {
+						m_bios_vendor = strings[x->vendor];
+					}
+				} break;
+
+				case types::processor_info: {
+					auto *const x = reinterpret_cast<proc_info *>(header);
+
+					if (x->length == 0) break;
+					if (x->manufacturer > 0 && x->manufacturer < x->length) {
+						m_cpu_manufacturer = strings[x->manufacturer];
+					}
+					m_cpu_cores = static_cast<unsigned int>(x->cores);
+				} break;
+
+				case types::system_info: {
+					auto *const x = reinterpret_cast<system_info *>(header);
+
+					if (x->length == 0) break;
+					if (x->manufacturer > 0 && x->manufacturer<x->length && x-> product_name > 0 &&
+						x->product_name < x->length) {
+						m_bios_description =
+							std::string(strings[x->manufacturer]) + std::string(strings[x->product_name]);
+					}
+				} break;
+				default:;
+			}
+		}
+		//smbios_parser.clear();
+	}
+	else {
+
+	}
 }
 }
 } /* namespace license */
diff --git a/src/library/os/windows/smbios.hpp b/src/library/os/windows/smbios.hpp
new file mode 100644
index 0000000..1209758
--- /dev/null
+++ b/src/library/os/windows/smbios.hpp
@@ -0,0 +1,397 @@
+/**
+ * Credits to:
+ * https://github.com/789sdf987s/hwid_generation
+ */
+#ifndef SMBIOS_H
+#define SMBIOS_H
+#pragma once
+
+#include <Windows.h>
+#include <cstdint>
+#include <vector>
+
+namespace smbios {
+namespace types {
+enum {
+	bios_info = 0,
+	// Required
+	system_info = 1,
+	// Required
+	baseboard_info = 2,
+	module_info = 2,
+	system_enclosure = 3,
+	// Required
+	system_chassis = 3,
+	// Required
+	processor_info = 4,
+	// Required
+	memory_controller_info = 5,
+	// Obsolete
+	memory_module_info = 6,
+	// Obsolete
+	cache_info = 7,
+	// Required
+	port_connector_info = 8,
+	system_slots = 9,
+	// Required
+	onboard_device_info = 10,
+	// Obsolete
+	oem_strings = 11,
+	system_config_options = 12,
+	language_info = 13,
+	group_associations = 14,
+	system_event_log = 15,
+	memory_array = 16,
+	// Required
+	memory_device = 17,
+	// Required
+	memory_error_info_32_bit = 18,
+	memory_array_mapped_addr = 19,
+	// Required
+	memory_device_mapped_addr = 20,
+	builtin_pointing_device = 21,
+	portable_battery = 22,
+	system_reset = 23,
+	hardware_security = 24,
+	system_power_controls = 25,
+	voltage_probe = 26,
+	cooling_device = 27,
+	temperature_probe = 28,
+	electrical_current_probe = 29,
+	out_of_band_remote_access = 30,
+	bis_entry_point = 31,
+	// Required
+	system_boot_info = 32,
+	// Required
+	memory_error_info_64_bit = 33,
+	management_device = 34,
+	management_device_component = 35,
+	management_device_threshold = 36,
+	memory_channel = 37,
+	ipmi_device_info = 38,
+	system_power_supply = 39,
+	additional_info = 40,
+	onboard_device_extinfo = 41,
+	management_controller_host = 42,
+	inactive = 126,
+	end_of_table = 127,
+// Always last structure
+};
+}
+
+typedef uint8_t byte_t;
+typedef uint16_t word_t;
+typedef uint32_t dword_t;
+
+#ifdef _MSC_VER
+	typedef __int64 qword_t;
+#else
+#ifdef INT64_C
+	typedef uint64_t qword_t;
+#else
+typedef (unsigned long long int) qwordt_t;
+#endif
+#endif
+
+typedef byte_t str_id;
+typedef byte_t enum_t;
+
+typedef std::vector<char*> string_array_t;
+
+struct header;
+
+#pragma pack(push, 1)
+
+struct raw_smbios_data {
+	BYTE used20_calling_method;
+	BYTE smbios_major_version;
+	BYTE smbios_minor_version;
+	BYTE dmi_revision;
+	DWORD length;
+	BYTE smbios_table_data[1];
+};
+
+struct header {
+	byte_t type;
+	byte_t length;
+	word_t handle;
+};
+
+struct string_list: header {
+	byte_t count;
+};
+
+struct baseboard_info: header {
+	byte_t manufacturer_name;
+	byte_t product_name;
+	byte_t version;
+	byte_t serial_number;
+	byte_t product;
+	byte_t version1;
+	byte_t serial_number1;
+};
+
+struct bios_info: header {
+	// 2.0
+	str_id vendor;
+	str_id version;
+	word_t starting_segment;
+	str_id release_date;
+	byte_t rom_size;
+	qword_t characteristics;
+	// 2.4
+	byte_t ext_char1;
+	byte_t ext_char2;
+	byte_t sb_major;
+	byte_t sb_minor;
+	byte_t ec_major;
+	byte_t ec_minor;
+};
+
+struct system_info: header {
+	// 2.0
+	str_id manufacturer;
+	str_id product_name;
+	str_id version;
+	str_id serial_number;
+
+	// 2.1
+	struct {
+		dword_t time_low;
+		word_t time_mid;
+		word_t time_hi_and_version;
+		byte_t clock_seq_hi_and_reserved;
+		byte_t clock_seq_low;
+		byte_t node[6];
+	} uuid;
+
+	enum_t wakeup_type;
+	// 2.4
+	str_id sku;
+	str_id family;
+};
+
+struct system_chassis: header {
+	// 2.0
+	str_id manufacturer;
+	byte_t type;
+	str_id version;
+	str_id serial_number;
+	str_id assert_tag;
+	// 2.1
+	enum_t bootup_state;
+	enum_t power_supply_state;
+	enum_t thermal_state;
+	enum_t security_status;
+	// 2.3
+	dword_t oem;
+	byte_t height;
+	byte_t cords;
+};
+
+struct proc_info: header {
+	// 2.0
+	str_id socket_designation;
+	enum_t type;
+	enum_t family;
+	str_id manufacturer;
+	qword_t id;
+	str_id version;
+	byte_t voltage;
+	word_t clock;
+	word_t speed_max;
+	word_t speed_cur;
+	byte_t status;
+	enum_t upgrade;
+	// 2.1
+	word_t l1;
+	word_t l2;
+	word_t l3;
+	// 2.3
+	str_id serial_number;
+	str_id assert_tag;
+	str_id part_number;
+	// 2.5
+	byte_t cores;
+	byte_t cores_enabled;
+	byte_t threads;
+	word_t characteristics;
+	enum_t family2;
+};
+
+struct cache_info: header {
+	// 2.0
+	str_id socket_designation;
+	word_t config;
+	word_t size_max;
+	word_t size_cur;
+	word_t sram_supported;
+	word_t sram_cur;
+	// 2.1
+	byte_t speed;
+	enum_t error_correction_type;
+	enum_t system_cache_type;
+	enum_t associativity;
+};
+
+struct slot: header {
+	// 2.0
+	str_id slot_designation;
+	enum_t type;
+	enum_t data_bus_width;
+	enum_t current_usage;
+	enum_t length;
+	word_t id;
+	byte_t characteristics;
+	// 2.1
+	byte_t characteristics2;
+	// 2.6
+	word_t segment_group;
+	byte_t bus;
+	byte_t device;
+};
+
+typedef string_list oem_strings;
+typedef string_list system_config_options;
+
+struct lang_info: header {
+	byte_t installed_langs;
+	byte_t flags;
+	byte_t reserved[15];
+	str_id current_lang;
+};
+
+struct mem_arr: header {
+	// 2.1
+	enum_t location;
+	enum_t use;
+	enum_t error_correction;
+	dword_t capacity;
+	word_t error_info_handle;
+	word_t devices_number;
+	// 2.7
+	qword_t capacity_ext;
+};
+
+struct mem_device: header {
+	// 2.1
+	word_t mem_arr_handle;
+	word_t mem_arr_error_info_handle;
+	word_t total_width;
+	word_t data_width;
+	word_t size;
+	enum_t form_factor;
+	byte_t device_set;
+	str_id device_locator;
+	str_id bank_locator;
+	enum_t type;
+	word_t type_detail;
+	// 2.3
+	word_t speed;
+	str_id manufacturer;
+	str_id serial_number;
+	str_id assert_tag;
+	str_id part_number;
+	// 2.6
+	byte_t attributes;
+	// 2.7
+	dword_t size_ext;
+	word_t clock_speed;
+	// 2.8
+	word_t voltage_min;
+	word_t voltage_max;
+	word_t voltage;
+};
+
+#pragma pack(pop)
+
+class parser final {
+public:
+	parser() = default;
+
+	parser(const parser &x) {
+		feed(x.raw_data_, x.raw_size_);
+	}
+
+	~parser() {
+		clear();
+	}
+
+	std::vector<header*> headers;
+
+	static byte_t* skip(byte_t*);
+
+	static header* extract_strings(header*, string_array_t&);
+
+	void feed(const void *raw_smbios, size_t size);
+
+	void clear();
+
+protected:
+	byte_t *raw_data_ { };
+
+	size_t raw_size_ { };
+};
+
+inline byte_t* parser::skip(byte_t *x) {
+	auto *ptr = x + reinterpret_cast<header*>(x)->length;
+	size_t len;
+
+	if (*ptr == 0)
+		ptr += 2;
+	else
+		do {
+			len = strlen(reinterpret_cast<const char*>(ptr));
+			ptr += len + 1;
+		} while (len > 0);
+
+	return ptr;
+}
+
+inline header* parser::extract_strings(header *x, string_array_t &a) {
+	auto *ptr = reinterpret_cast<byte_t*>(x) + x->length;
+
+	a.clear();
+	a.push_back(nullptr);
+
+	if (*ptr == 0)
+		ptr += 2;
+	else
+		for (;;) {
+			auto *str = reinterpret_cast<char*>(ptr);
+			const auto len = strlen(str);
+
+			ptr += len + 1;
+
+			if (len == 0)
+				break;
+
+			a.push_back(str);
+		}
+
+	return reinterpret_cast<header*>(ptr);
+}
+
+inline void parser::feed(const void *raw_smbios, const size_t size) {
+	clear();
+
+	raw_size_ = size;
+	raw_data_ = new byte_t[raw_size_];
+
+	memcpy(raw_data_, raw_smbios, size);
+
+	auto *x = raw_data_;
+
+	while (static_cast<size_t>(x - raw_data_) < raw_size_) {
+		headers.push_back(reinterpret_cast<header*>(x));
+		x = skip(x);
+	}
+}
+
+inline void parser::clear() {
+	headers.clear();
+	delete[] raw_data_;
+	raw_size_ = 0;
+}
+} // namespace smbios
+#endif
diff --git a/test/library/os/dmi_info_test.cpp b/test/library/os/dmi_info_test.cpp
index ac29cc6..5f44d62 100644
--- a/test/library/os/dmi_info_test.cpp
+++ b/test/library/os/dmi_info_test.cpp
@@ -12,13 +12,11 @@
 
 BOOST_AUTO_TEST_CASE(dmi_info) {
 	os::DmiInfo dmiInfo;
-//windows bug
 
-#ifdef __unix__
 	BOOST_CHECK_MESSAGE(dmiInfo.bios_vendor().size()>0, "Bios vendor OK");
 	BOOST_CHECK_MESSAGE(dmiInfo.bios_description().size() > 0, "Bios description OK");
 	BOOST_CHECK_MESSAGE(dmiInfo.sys_vendor().size() > 0, "Sys vendor OK");
-#endif
+
 }
 
 }  // namespace test

--
Gitblit v1.9.1