├── .gitignore ├── test-run ├── CMakeLists.txt └── main.cpp ├── hardware_gen.hpp ├── implementation ├── mac │ ├── mac_manager.hpp │ └── mac_manager.cpp ├── version.hpp ├── util.hpp ├── log.hpp ├── linux │ ├── linux_manager.hpp │ └── linux_manager.cpp ├── log.cpp ├── md5.hpp ├── util.cpp ├── version.cpp ├── windows │ ├── windows_manager.hpp │ └── windows_manager.cpp └── md5.cpp ├── CMakeLists.txt └── hardware_gen.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeLists.txt.user 2 | /bin 3 | /test-run/bin 4 | /test-run/CMakeLists.txt.user 5 | -------------------------------------------------------------------------------- /test-run/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | 3 | project( test_exec ) 4 | 5 | add_executable( test_exec main.cpp ) 6 | 7 | set( CMAKE_CXX_FLAGS "-std=c++11" ) 8 | 9 | find_library( HARDWARE_ID_LIB "HardwareIdGenerator" "${CMAKE_SOURCE_DIR}/bin/" ) 10 | TARGET_LINK_LIBRARIES( test_exec ${HARDWARE_ID_LIB} ) 11 | -------------------------------------------------------------------------------- /test-run/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../hardware_gen.hpp" 2 | // Чтобы линковщик нашел библиотеку, 3 | // она должна находиться там же, где 4 | // исполняемый файл 5 | 6 | #include 7 | #include 8 | 9 | int main( int argc, char* argv[] ) 10 | { 11 | const int buffSize = 200; 12 | char memory[ buffSize ]; 13 | memset( memory, '\0', buffSize ); 14 | 15 | // Получение HardwareID 16 | GetHardwareId( memory, "1.4", "" ); 17 | std::string hid( memory ); 18 | 19 | // Выводим результат 20 | if( hid.size() > 0 ) 21 | std::cout << hid << std::endl ; 22 | else 23 | return -1; 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /hardware_gen.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" 5 | { 6 | #endif 7 | 8 | 9 | #ifndef DLL_EXPORT 10 | #ifdef SYSTEM_WINDOWS 11 | #define DLL_EXPORT __declspec(dllexport) 12 | #else 13 | #define DLL_EXPORT extern 14 | #endif 15 | #endif 16 | 17 | /** 18 | * @brief Получить идентификатор железа (HID) 19 | * @param hardwareIdResult Результат - буфер для идентификатора 20 | * @param version Версия алгоритма 21 | * @param logPath Путь к папке логирования 22 | */ 23 | DLL_EXPORT void GetHardwareId( char* hardwareIdResult, const char* version, const char* logPath ); 24 | 25 | /** 26 | * @brief Получить версию библиотеки 27 | * @param libVersion Результат - буфер для версии 28 | */ 29 | DLL_EXPORT void GetVersion( char* libVersion ); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /implementation/mac/mac_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace system_info 6 | { 7 | 8 | struct Version; 9 | 10 | /** 11 | * @brief Класс для работы с железом 12 | * в MAC OS X 13 | */ 14 | class NativeOSManager 15 | { 16 | public: 17 | /** 18 | * @brief Получить строку с идентификаторами железа 19 | * @param hidVersion Версия алгоритма 20 | * @return Строка с идентификаторами железа, следующими 21 | * друг за другом 22 | */ 23 | static std::string GetHardwareProperties( const Version& hidVersion ); 24 | private: 25 | /** 26 | * @brief Получить указанное свойство сервиса IOPlatform 27 | * @param property Свойство, чье значение нужно получить 28 | * @return Значение указанного свойства 29 | */ 30 | static std::string GetIOPlatformProperty( const std::string& property ); 31 | 32 | /** 33 | * @brief Получить указанное свойство сервиса IONetwork 34 | * @param property Свойство, чье значение нужно получить 35 | * @return Значение указанного свойства 36 | */ 37 | static std::string GetIONetworkProperty( const std::string& property ); 38 | 39 | /** 40 | * @brief Получить указанное свойство сервиса IOStorage 41 | * @param property Свойство, чье значение нужно получить 42 | * @return Значение указанного свойства 43 | */ 44 | static std::string GetIOStorageProperty( const std::string& property ); 45 | }; 46 | 47 | } // end namespace system_info 48 | -------------------------------------------------------------------------------- /implementation/version.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace system_info 6 | { 7 | 8 | /** 9 | * @brief Структура, описывающая версию 10 | */ 11 | struct Version 12 | { 13 | /** 14 | * @brief Конструктор по умолчанию 15 | */ 16 | Version() { } 17 | 18 | /** 19 | * @brief Конструктор с параметром 20 | * @param versionStr Версия в строковом виде 21 | * @example "1.0", "2.1" 22 | */ 23 | Version( const std::string& versionStr ); 24 | 25 | /** 26 | * @brief Получить строковое представление версии 27 | * @return Строковое представление версии 28 | */ 29 | std::string ToString() const; 30 | 31 | /** 32 | * @brief Получить версию из строкого представления 33 | * @param versionStr Версия в строковом формате 34 | * @return Версия 35 | */ 36 | static Version GetVersionFromString( const std::string& versionStr ); 37 | 38 | // Главный номер версии 39 | unsigned MajorVersion = 0; 40 | 41 | // Младший номер версии 42 | unsigned MinorVersion = 0; 43 | }; 44 | 45 | // Операторы сравнивания версий 46 | bool operator<( const Version& version1, const Version& version2 ); 47 | bool operator==( const Version& version1, const Version& version2 ); 48 | bool operator!=( const Version& version1, const Version& version2 ); 49 | bool operator>=( const Version& version1, const Version& version2 ); 50 | bool operator<=( const Version& version1, const Version& version2 ); 51 | bool operator>( const Version& version1, const Version& version2 ); 52 | 53 | } // end namespace system_info 54 | -------------------------------------------------------------------------------- /implementation/util.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace system_info 6 | { 7 | 8 | // Предварительное объявление 9 | struct Version; 10 | 11 | /** 12 | * @brief Класс-помощник и различными 13 | * вспомогательными функциями 14 | */ 15 | class Util 16 | { 17 | public: 18 | /** 19 | * @brief Получить текущее время 20 | * @return Время в строковом формате типа [час:мин:сек:мс] 21 | */ 22 | static std::string GetTime(); 23 | 24 | /** 25 | * @brief Сформировать из 32-символьной строки (хеша) 26 | * полноценный UUID с префиксом-версией алгоритма 27 | * @param hash 32 символьная строка 28 | * @param version Версия алгоритма 29 | * @return UUID с префиксом-версией 30 | */ 31 | static std::string HashToUUID( const std::string& hash, const Version& version ); 32 | 33 | /** 34 | * @brief Преобразует строку из широких символов в 35 | * соответствующую ей строку многобайтовых символов 36 | * @param ws Широкая строка 37 | * @return Сооветствующая ей узкая строка 38 | * @warning Поскольку является оберткой для wcstombs, 39 | * может не распознавать некоторые символы, и таким образом 40 | * возвращать пустую строку 41 | */ 42 | static std::string WstringToString( const std::wstring& ws ); 43 | private: 44 | /** 45 | * @brief Поменять местами байты в строковом представлении 46 | * @param uuid 32 символьная строка 47 | * @param begin Начало секции 48 | * @param end Конец секции 49 | */ 50 | static void SwapUUIDBlocks( std::string& uuid, const int begin, const int end ); 51 | }; 52 | 53 | } // end namespace system_info 54 | -------------------------------------------------------------------------------- /implementation/log.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace system_info 6 | { 7 | 8 | /** 9 | * @brief Уровень логирования 10 | */ 11 | enum LogLevel 12 | { 13 | // Информационные сообщения (по умолчанию) 14 | Info, 15 | // Для отладки 16 | Debug, 17 | // Ошибка 18 | Error 19 | }; 20 | 21 | /** 22 | * @brief Класс для логирования информационных 23 | * сообщений 24 | */ 25 | class HIDLog 26 | { 27 | public: 28 | /** 29 | * @brief Указать папку для логирования 30 | * информационных сообщений 31 | * @param path Путь до папки, в которой будем логировать 32 | */ 33 | static void SetLogPath( const std::string& path ); 34 | 35 | /** 36 | * @brief Залогировать информационное сообщение 37 | * @param message Сообщение 38 | * @param level Уровень логирования 39 | */ 40 | static void Write( const std::string& message, LogLevel level = LogLevel::Info ); 41 | 42 | /** 43 | * @brief Залогировать информационное сообщение 44 | * @param message Сообщение (из широких символов) 45 | * @param level Уровень логирования 46 | */ 47 | static void Write( const std::wstring& message, LogLevel level = LogLevel::Info ); 48 | private: 49 | /** 50 | * @brief Преобразовать перечисление в стровой вид 51 | * @param level Уровень логирования 52 | * @return Соответствующее уровню логирования 53 | * строковое представление 54 | * @example LogLevel::Debug <-> "[Debug]" 55 | */ 56 | static std::string LogLevelToString( LogLevel level ); 57 | private: 58 | // Путь до файла с логированием 59 | static std::string fileLogPath; 60 | }; 61 | 62 | } // end namespace system_info 63 | -------------------------------------------------------------------------------- /implementation/linux/linux_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace system_info 7 | { 8 | 9 | // Предварительное объявление 10 | struct Version; 11 | 12 | /** 13 | * @brief Класс для работы с железом 14 | * в ОС Linux 15 | */ 16 | class NativeOSManager 17 | { 18 | public: 19 | /** 20 | * @brief Получить строку с идентификаторами железа 21 | * @param hidVersion Версия алгоритма 22 | * @return Строка с идентификаторами железа, следующими друг 23 | * за другом 24 | */ 25 | static std::string GetHardwareProperties( const Version& hidVersion ); 26 | private: 27 | /** 28 | * @brief Получить свойство DMI 29 | * @param service Целевой сервис 30 | * @param property Целевое свойство 31 | * @return Значение свойства указанного сервиса 32 | */ 33 | static std::string GetDmiProperty( const std::string& service, const std::string& property ); 34 | 35 | /** 36 | * @brief Получить серийный номер жесткого диска 37 | * @return Серийный номер жесткого диска 38 | */ 39 | static std::string GetHDDSerialNumber(); 40 | 41 | /** 42 | * @brief Получить МАС-адрес 43 | * @return МАС-адрес сетевого устройства 44 | */ 45 | static std::string GetMACAddress(); 46 | 47 | /** 48 | * @brief Получить дочерние объекты указанного типа из директории 49 | * @param folder Директория 50 | * @param itemList Результат (список объектов) 51 | * @param type Тип искомых объектов 52 | * @return True - если все ок, иначе false 53 | */ 54 | static bool GetItemsFromFolder( const std::string& folder, std::vector< std::string >& itemList, int type ); 55 | }; 56 | 57 | } // end namespace system_info 58 | -------------------------------------------------------------------------------- /implementation/log.cpp: -------------------------------------------------------------------------------- 1 | #include "log.hpp" 2 | #include "util.hpp" 3 | 4 | #include 5 | #include 6 | 7 | namespace system_info 8 | { 9 | 10 | std::string HIDLog::fileLogPath = ""; 11 | 12 | void HIDLog::SetLogPath( const std::string &path ) 13 | { 14 | if( path.empty() ) 15 | return; 16 | 17 | fileLogPath = path; 18 | 19 | // Если папка указана без разделителя в конце, вставляем сами 20 | if( fileLogPath.at( fileLogPath.size() - 1 ) != '/' || 21 | fileLogPath.at( fileLogPath.size() - 1 ) != '\\' ) 22 | fileLogPath += "/"; 23 | 24 | // Имя файла-лога 25 | fileLogPath += "hid.log"; 26 | } 27 | 28 | void HIDLog::Write( const std::string& message, LogLevel level ) 29 | { 30 | if( fileLogPath.empty() ) 31 | return; 32 | 33 | const int timeColumnWidth = 15; 34 | const int logLevelWidth = 7; 35 | 36 | std::ofstream file( fileLogPath, std::ios::in | std::ios::out | std::ios::app ); 37 | if( file.is_open() ) 38 | { 39 | file << std::setw( timeColumnWidth ) << std::left << Util::GetTime() 40 | << std::setw( logLevelWidth ) << std::left << LogLevelToString( level ) 41 | << " " << message << std::endl; 42 | file.close(); 43 | } 44 | } 45 | 46 | void HIDLog::Write( const std::wstring& message, LogLevel level ) 47 | { 48 | Write( Util::WstringToString( message ), level ); 49 | } 50 | 51 | std::string HIDLog::LogLevelToString( LogLevel level ) 52 | { 53 | switch( level ) 54 | { 55 | case LogLevel::Error: 56 | return "[Error]"; 57 | case LogLevel::Debug: 58 | return "[Debug]"; 59 | case LogLevel::Info: 60 | default: 61 | return "[Info]"; 62 | } 63 | } 64 | 65 | } // end namespace system_info 66 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | 3 | project( HardwareIdGenerator ) 4 | 5 | set( HID_GEN_SOURCES 6 | "hardware_gen.hpp" "hardware_gen.cpp" 7 | "implementation/md5.hpp" "implementation/md5.cpp" 8 | "implementation/version.hpp" "implementation/version.cpp" 9 | "implementation/util.hpp" "implementation/util.cpp" 10 | "implementation/log.hpp" "implementation/log.cpp" ) 11 | 12 | # Для каждой ОС загружаем специфичный ей сервис для работы с ситемой 13 | # и по мере надобности загружаем / определяем глобальные переменные 14 | # и библиотеки для работы с системой 15 | if( WIN32 ) 16 | set( NATIVE_SOURCES 17 | "implementation/windows/windows_manager.hpp" "implementation/windows/windows_manager.cpp" ) 18 | add_definitions( -DSYSTEM_WINDOWS ) 19 | 20 | add_definitions( -D_WIN32_LEAN_AND_MEAN ) 21 | add_definitions( -D_WIN32_WINNT=0x0600 ) 22 | 23 | elseif( UNIX AND NOT APPLE ) 24 | set( NATIVE_SOURCES 25 | "implementation/linux/linux_manager.hpp" "implementation/linux/linux_manager.cpp" ) 26 | add_definitions( -DSYSTEM_LINUX ) 27 | 28 | elseif( APPLE ) 29 | set( NATIVE_SOURCES 30 | "implementation/mac/mac_manager.hpp" "implementation/mac/mac_manager.cpp" ) 31 | add_definitions( -DSYSTEM_MAC ) 32 | endif() 33 | 34 | add_library( ${PROJECT_NAME} SHARED ${HID_GEN_SOURCES} ${NATIVE_SOURCES} ) 35 | 36 | set( CMAKE_CXX_FLAGS "-std=c++11" ) 37 | 38 | if( APPLE ) 39 | include_directories( "Developer/Headers/FlatCarbon" ) 40 | find_library( CARBON_LIBRARY Carbon ) 41 | find_library( IOKIT_LIBRARY IOKit ) 42 | mark_as_advanced( CARBON_LIBRARY IOKIT_LIBRARY ) 43 | set( EXTRA_LIBS ${CARBON_LIBRARY} ${IOKIT_LIBRARY} ) 44 | target_link_libraries( ${PROJECT_NAME} ${EXTRA_LIBS} ) 45 | endif() 46 | -------------------------------------------------------------------------------- /implementation/md5.hpp: -------------------------------------------------------------------------------- 1 | // http://www.zedwood.com/article/cpp-md5-function 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace system_info 8 | { 9 | 10 | static const int blocksize = 64; 11 | 12 | /** 13 | * @brief Класс для получения MD5 хеша 14 | */ 15 | class MD5 16 | { 17 | public: 18 | MD5(); 19 | MD5( const std::string& text ); 20 | void Update( const unsigned char *buf, std::uint32_t length ); 21 | void Update( const char *buf, std::uint32_t length ); 22 | MD5& Finalize(); 23 | std::string HexDigest() const; 24 | private: 25 | void Init(); 26 | void Transform( const std::uint8_t block[ blocksize ] ); 27 | static void Decode( std::uint32_t output[], const std::uint8_t input[], std::uint32_t len ); 28 | static void Encode( std::uint8_t output[], const std::uint32_t input[], std::uint32_t len ); 29 | 30 | ////////////////// НИЗКОУРОВНЕВЫЕ ОПЕРАЦИИ ////////////////// 31 | static inline std::uint32_t F( std::uint32_t x, std::uint32_t y, std::uint32_t z ); 32 | static inline std::uint32_t G( std::uint32_t x, std::uint32_t y, std::uint32_t z ); 33 | static inline std::uint32_t H( std::uint32_t x, std::uint32_t y, std::uint32_t z ); 34 | static inline std::uint32_t I( std::uint32_t x, std::uint32_t y, std::uint32_t z ); 35 | static inline std::uint32_t RotateLeft( std::uint32_t x, int n ); 36 | static inline void FF( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t s, std::uint32_t ac ); 37 | static inline void GG( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t s, std::uint32_t ac ); 38 | static inline void HH( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t s, std::uint32_t ac ); 39 | static inline void II( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t s, std::uint32_t ac ); 40 | private: 41 | bool finalized = true; 42 | std::uint8_t buffer[ blocksize ]; 43 | std::uint32_t count[ 2 ]; 44 | std::uint32_t state[ 4 ]; 45 | std::uint8_t digest[ 16 ]; 46 | }; 47 | 48 | } // end namespace system_info 49 | -------------------------------------------------------------------------------- /implementation/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | #include "version.hpp" 3 | 4 | #include 5 | 6 | namespace system_info 7 | { 8 | 9 | std::string Util::GetTime() 10 | { 11 | std::string timeStr = "["; 12 | 13 | const std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); 14 | std::chrono::system_clock::duration tp = now.time_since_epoch(); 15 | 16 | tp -= std::chrono::duration_cast< std::chrono::seconds >( tp ); 17 | const time_t tt = std::chrono::system_clock::to_time_t( now ); 18 | const tm* currentTime = localtime( &tt ); 19 | 20 | timeStr += std::to_string( currentTime->tm_hour ) + ":"; 21 | timeStr += std::to_string( currentTime->tm_min ) + ":"; 22 | timeStr += std::to_string( currentTime->tm_sec ) + ":"; 23 | timeStr += std::to_string( tp / std::chrono::milliseconds( 1 ) ); 24 | 25 | timeStr += "]"; 26 | return timeStr; 27 | } 28 | 29 | std::string Util::HashToUUID( const std::string& hash, const Version& version ) 30 | { 31 | std::string uuid = hash; 32 | 33 | SwapUUIDBlocks( uuid, 0, 8 ); 34 | SwapUUIDBlocks( uuid, 8, 12 ); 35 | SwapUUIDBlocks( uuid, 12, 16 ); 36 | SwapUUIDBlocks( uuid, 16, 20 ); 37 | 38 | int offset = 0; 39 | uuid.insert( 8, "-" ); 40 | uuid.insert( 12 + ++offset, "-" ); 41 | uuid.insert( 16 + ++offset, "-" ); 42 | uuid.insert( 20 + ++offset, "-" ); 43 | 44 | if( version > Version( "1.0" ) ) 45 | { 46 | uuid.insert( 0, std::to_string( version.MinorVersion ) + "-" ); 47 | uuid.insert( 0, std::to_string( version.MajorVersion ) + "-" ); 48 | } 49 | 50 | return uuid; 51 | } 52 | 53 | std::string Util::WstringToString( const std::wstring& ws ) 54 | { 55 | const size_t wlen = ws.size(); 56 | char buf[ wlen * sizeof( std::wstring::value_type ) + 1 ]; 57 | const ssize_t res = std::wcstombs( buf, ws.c_str(), sizeof( buf ) ); 58 | return ( res < 0 ) ? "" : buf; 59 | } 60 | 61 | void Util::SwapUUIDBlocks( std::string& uuid, const int begin, const int end ) 62 | { 63 | for( int i = begin; i < ( begin + end ) / 2 ; i += 2 ) 64 | { 65 | char temp1 = uuid[ i ]; 66 | char temp2 = uuid[ i + 1 ]; 67 | uuid[ i ] = uuid[ end + begin - i - 2 ]; 68 | uuid[ i + 1 ] = uuid[ end + begin - i - 1 ]; 69 | uuid[ end + begin - i - 2 ] = temp1; 70 | uuid[ end + begin - i - 1 ] = temp2; 71 | } 72 | } 73 | 74 | } // end namespace system_info 75 | -------------------------------------------------------------------------------- /hardware_gen.cpp: -------------------------------------------------------------------------------- 1 | #include "hardware_gen.hpp" 2 | #include "implementation/log.hpp" 3 | #include "implementation/md5.hpp" 4 | #include "implementation/util.hpp" 5 | #include "implementation/version.hpp" 6 | 7 | #if defined( SYSTEM_WINDOWS ) 8 | #include "implementation/windows/windows_manager.hpp" 9 | #elif defined( SYSTEM_LINUX ) 10 | #include "implementation/linux/linux_manager.hpp" 11 | #elif defined( SYSTEM_MAC ) 12 | #include "implementation/mac/mac_manager.hpp" 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace system_info; 20 | 21 | void GetHardwareId( char* hardwareIdResult, const char* versionStr, const char* logPath ) 22 | { 23 | try 24 | { 25 | // Инициализация логгера 26 | HIDLog::SetLogPath( logPath ); 27 | HIDLog::Write( "Выполняется метод GetHardwareId", LogLevel::Debug ); 28 | 29 | // Получаем HID заданной версии 30 | const Version version( versionStr ); 31 | std::string hid = NativeOSManager::GetHardwareProperties( version ); 32 | 33 | // Если не удалось получать никаких данных о железе - генерируем случайную строку 34 | if( hid.empty() ) 35 | { 36 | HIDLog::Write( "Не удалось получить ни один из всех идентификаторов железа. " 37 | "Будет сгенерирован случайный UUID", LogLevel::Debug ); 38 | std::srand( std::time( nullptr ) ); 39 | int rand = std::rand(); 40 | hid = std::to_string( rand ); 41 | } 42 | else 43 | HIDLog::Write( "Идентификаторы получены.", LogLevel::Debug ); 44 | 45 | // Получаем MD5 хеш данных о железе - есть наш UUID 46 | MD5 md5( hid ); 47 | std::string md5hash = md5.HexDigest(); 48 | std::string uuid = Util::HashToUUID( md5hash, version ); 49 | HIDLog::Write( "Получен HID: " + uuid, LogLevel::Debug ); 50 | 51 | // Копируем результат в буффер 52 | memset( hardwareIdResult, '\0', uuid.size() + 1 ); 53 | memcpy( hardwareIdResult, uuid.c_str(), uuid.size() + 1 ); 54 | } 55 | catch( ... ) 56 | { 57 | HIDLog::Write( "Непредсказуемая ошибка в GetHardwareId", LogLevel::Error ); 58 | } 59 | } 60 | 61 | static const std::string libraryVersion = "1.4"; 62 | 63 | void GetVersion( char *libVersion ) 64 | { 65 | // Копируем результат в буффер 66 | memset( libVersion, '\0', libraryVersion.size() + 1 ); 67 | memcpy( libVersion, libraryVersion.c_str(), libraryVersion.size() + 1 ); 68 | } 69 | -------------------------------------------------------------------------------- /implementation/version.cpp: -------------------------------------------------------------------------------- 1 | #include "version.hpp" 2 | #include "log.hpp" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace system_info 10 | { 11 | 12 | Version::Version( const std::string& versionStr ) 13 | { 14 | *this = GetVersionFromString( versionStr ); 15 | } 16 | 17 | std::string Version::ToString() const 18 | { 19 | return std::to_string( MajorVersion ) + "." + std::to_string( MinorVersion ); 20 | } 21 | 22 | Version Version::GetVersionFromString( const std::string& versionStr ) 23 | { 24 | Version version; 25 | 26 | std::string versionWithSpaces = versionStr; 27 | std::replace( versionWithSpaces.begin(), versionWithSpaces.end(), '.', ' ' ); 28 | 29 | std::istringstream iss( versionWithSpaces ); 30 | const std::vector< std::string > results( ( std::istream_iterator< std::string >( iss ) ), 31 | std::istream_iterator< std::string>() ); 32 | 33 | if( results.size() != 2 ) 34 | { 35 | HIDLog::Write( "Строка с номером версии задана некорретно." 36 | "Значение по умолчанию 1.0", LogLevel::Error ); 37 | version.MajorVersion = 1; 38 | version.MinorVersion = 0; 39 | return version; 40 | } 41 | 42 | version.MajorVersion = std::stoi( results[ 0 ] ); 43 | version.MinorVersion = std::stoi( results[ 1 ] ); 44 | 45 | return version; 46 | } 47 | 48 | bool operator<( const Version& version1, const Version& version2 ) 49 | { 50 | if( version1.MajorVersion < version2.MajorVersion ) 51 | return true; 52 | else if( version1.MajorVersion == version2.MajorVersion ) 53 | if( version1.MinorVersion < version2.MinorVersion ) 54 | return true; 55 | 56 | return false; 57 | } 58 | 59 | bool operator==( const Version& version1, const Version& version2 ) 60 | { 61 | if( version1.MajorVersion == version2.MajorVersion && 62 | version1.MinorVersion == version2.MinorVersion ) 63 | return true; 64 | 65 | return false; 66 | } 67 | 68 | bool operator!=( const Version& version1, const Version& version2 ) 69 | { 70 | return !( version1 == version2 ); 71 | } 72 | 73 | bool operator>=( const Version& version1, const Version& version2 ) 74 | { 75 | return !( version1 < version2 ); 76 | } 77 | 78 | bool operator<=( const Version& version1, const Version& version2 ) 79 | { 80 | return ( version1 == version2 ) || ( version1 < version2 ); 81 | } 82 | 83 | bool operator>( const Version& version1, const Version& version2 ) 84 | { 85 | return !( ( version1 == version2 ) || ( version1 < version2 ) ); 86 | } 87 | 88 | } // end namespace system_info 89 | -------------------------------------------------------------------------------- /implementation/windows/windows_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Предварительное объявление 6 | struct IWbemServices; 7 | using BSTR = wchar_t*; 8 | using GUID = struct _GUID; 9 | using CLSID = GUID; 10 | using IID = GUID; 11 | 12 | namespace system_info 13 | { 14 | 15 | // Предварительное объявление 16 | struct Version; 17 | 18 | /** 19 | * @brief Класс для работы с железом 20 | * в ОС Windows 21 | */ 22 | class NativeOSManager 23 | { 24 | public: 25 | /** 26 | * @brief Получить строку с идентификаторами железа (обертка) 27 | * @param version Версия алгоритма 28 | * @return Строка с идентификаторами железа, следующими 29 | * друг за другом 30 | */ 31 | static std::string GetHardwareProperties( const Version& version ); 32 | private: 33 | /** 34 | * @brief Перевести строку в нижний регистр 35 | * @param string Результат с символами в нижнем регистре 36 | */ 37 | static void ToLower( std::wstring& string ); 38 | 39 | /** 40 | * @brief Получить строку с идентификаторами железа 41 | * @param hidVeriosn Версия алгоритма 42 | * @return Строка с идентификаторами железа, следующими 43 | * друг за другом 44 | */ 45 | static std::wstring GetWmiProperties( const Version& hidVeriosn ); 46 | 47 | /** 48 | * @brief Получить значение свойства класса через WMI 49 | * @param services Интерфейс для взаимодействия с WMI 50 | * @param classname Целевой класс 51 | * @param property Целевое свойство класса 52 | * @param check Проверка на пустое значение 53 | * @return Значение указанного свойства класса 54 | */ 55 | static std::wstring GetWmiProperty( IWbemServices* services, const wchar_t* classname, const wchar_t* property, bool check = true ); 56 | 57 | /** 58 | * @brief Получить идентификатор раздела жесткого диска 59 | * @param services Интерфейс для взаимодействия с WMI 60 | * @param check Алгоритм старше версии 1.2? 61 | * @return Значение идентификатора раздела жесткого диска 62 | */ 63 | static std::wstring GetWmiPropertyForHdd( IWbemServices* services, bool check ); 64 | 65 | /** 66 | * @brief Получить MAC-адрес 67 | * @param services Интерфейс для взаимодействия с WMI 68 | * @return Значние MAC-адреса 69 | */ 70 | static std::wstring GetWmiPropertyForNetworkAdapter( IWbemServices* services ); 71 | 72 | /** 73 | * @brief Обработать системное значение 74 | * @param prop Строка в формате BSTR 75 | * @param check Проверка на пустое значение. Если 76 | * включена, то пустое системное значние будет трактовано 77 | * как пустая строка 78 | * @return Значение в формате std::wstring 79 | */ 80 | static std::wstring ProcessWmiProperty( BSTR prop, bool check ); 81 | private: 82 | const static CLSID local_CLSID_WbemLocator; 83 | const static IID local_IID_IWbemLocator; 84 | }; 85 | 86 | } // end namespace system_info 87 | -------------------------------------------------------------------------------- /implementation/linux/linux_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "linux_manager.hpp" 2 | #include "../log.hpp" 3 | #include "../util.hpp" 4 | #include "../version.hpp" 5 | 6 | // Linux include specific 7 | #include 8 | 9 | // Standart include 10 | #include 11 | #include 12 | 13 | namespace system_info 14 | { 15 | 16 | std::string NativeOSManager::GetHardwareProperties( const Version& hidVersion ) 17 | { 18 | HIDLog::Write( "Получаем данные о железе в среде Linux", LogLevel::Debug ); 19 | std::string result = ""; 20 | 21 | result += GetDmiProperty( "product", "uuid" ); 22 | result += GetDmiProperty( "product", "serial" ); 23 | result += GetDmiProperty( "board", "serial" ); 24 | result += GetHDDSerialNumber(); 25 | result += GetMACAddress(); 26 | 27 | return result; 28 | } 29 | 30 | std::string NativeOSManager::GetDmiProperty( const std::string& service, const std::string& property ) 31 | { 32 | std::string result = ""; 33 | std::ifstream file( "/sys/class/dmi/id/" + service + "_" + property ); 34 | 35 | if( file.is_open() ) 36 | { 37 | std::getline( file, result ); 38 | file.close(); 39 | } 40 | 41 | HIDLog::Write( "Значение свойства \'" + property + "\' для \'" + service + "\'" 42 | " = \'" + result + "\'", LogLevel::Debug ); 43 | return result; 44 | } 45 | 46 | std::string NativeOSManager::GetHDDSerialNumber() 47 | { 48 | // Открываем директорию с идентификаторами жестких дисков 49 | const std::string uuidFolder = "/dev/disk/by-uuid/"; 50 | std::vector< std::string > uuids; 51 | 52 | if( !GetItemsFromFolder( uuidFolder, uuids, DT_LNK ) ) 53 | { 54 | HIDLog::Write( "Не смогли получить список идентификаторов" 55 | "в папке /dev/disk/by-uuid/", LogLevel::Debug ); 56 | return ""; 57 | } 58 | 59 | // Формируем словарь "служебное имя жесткого диска - UUID" 60 | // Коллекция упорядочена по ключу 61 | std::map< std::string, std::string > devices; 62 | char buffer[ 200 ]; 63 | for( const std::string& uuid : uuids ) 64 | { 65 | std::string uuidPath = uuidFolder + uuid; 66 | realpath( uuidPath.c_str(), buffer ); 67 | // Вставка происходит с сортировкой по ключу 68 | devices[ buffer ] = uuid; 69 | } 70 | 71 | // Находим самое раннее имя sda или hda и возвращаем его UUID 72 | for( const auto& item : devices ) 73 | { 74 | if ( item.first.find( "sda" ) != std::string::npos || 75 | item.first.find( "hda" ) != std::string::npos ) 76 | { 77 | HIDLog::Write( "Серийный номер жесткого диска: " + item.second, LogLevel::Debug ); 78 | return item.second; 79 | } 80 | } 81 | 82 | HIDLog::Write( "Не смогли получить серийный номер жесткого диска", LogLevel::Debug ); 83 | return ""; 84 | } 85 | 86 | std::string NativeOSManager::GetMACAddress() 87 | { 88 | // Открываем директорию с именами сетевых интерфейсов 89 | const std::string netFolder = "/sys/class/net/"; 90 | std::vector< std::string > netNames; 91 | 92 | if( !GetItemsFromFolder( netFolder, netNames, DT_LNK ) ) 93 | { 94 | HIDLog::Write( "Не смогли получить список идентификаторов" 95 | "в папке /sys/class/net/", LogLevel::Debug ); 96 | return ""; 97 | } 98 | 99 | // Формируем словарь "служебное имя сетевого устройства - сетевой адрес" 100 | // Коллекция упорядочена по ключу 101 | std::map< std::string, std::string > netDevices; 102 | std::string tempAddress = ""; 103 | for( const std::string& netName : netNames ) 104 | { 105 | std::string addressPath = netFolder + netName + "/address"; 106 | std::ifstream addressFile( addressPath ); 107 | tempAddress = ""; 108 | 109 | if( addressFile.is_open() ) 110 | { 111 | std::getline( addressFile, tempAddress ); 112 | addressFile.close(); 113 | } 114 | 115 | netDevices[ netName ] = tempAddress; 116 | } 117 | 118 | // Находим самое раннее имя eth или enp и возвращаем его сетевой адрес 119 | for( const auto& item : netDevices ) 120 | { 121 | if ( item.first.find( "eth" ) != std::string::npos || 122 | item.first.find( "enp" ) != std::string::npos ) 123 | { 124 | HIDLog::Write( "MAC-адрес: " + item.second, LogLevel::Debug ); 125 | return item.second; 126 | } 127 | } 128 | 129 | HIDLog::Write( "Не смогли получить MAC-адрес", LogLevel::Debug ); 130 | return ""; 131 | } 132 | 133 | bool NativeOSManager::GetItemsFromFolder( const std::string& folder, std::vector< std::string >& itemList , int type ) 134 | { 135 | DIR* dir = nullptr; 136 | if( !( dir = opendir( folder.c_str() ) ) ) 137 | return false; 138 | 139 | dirent *dirp = nullptr; 140 | while( ( dirp = readdir( dir ) ) ) 141 | { 142 | if( dirp->d_type == type ) 143 | itemList.push_back( std::string( dirp->d_name ) ); 144 | } 145 | 146 | closedir( dir ); 147 | return true; 148 | } 149 | 150 | } // end namespace system_info 151 | -------------------------------------------------------------------------------- /implementation/mac/mac_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "mac_manager.hpp" 2 | #include "../log.hpp" 3 | #include "../util.hpp" 4 | #include "../version.hpp" 5 | 6 | // MAC-specific include 7 | #include 8 | #include 9 | 10 | // STD include 11 | #include 12 | 13 | namespace system_info 14 | { 15 | 16 | struct CFStringWrapper 17 | { 18 | CFStringWrapper( CFStringRef cfStr ) 19 | { 20 | this->cfStr = cfStr; 21 | } 22 | 23 | CFStringWrapper( const std::string str ) 24 | { 25 | cfStr = CFStringCreateWithCString( kCFAllocatorDefault, str.c_str(), kCFStringEncodingASCII ); 26 | 27 | if( !cfStr ) 28 | throw std::exception(); 29 | } 30 | 31 | ~CFStringWrapper() 32 | { 33 | CFRelease( cfStr ); 34 | } 35 | 36 | std::string GetStdString() 37 | { 38 | if( cfStr ) 39 | { 40 | char buffer[ 500 ]; 41 | if( CFStringGetCString( cfStr, buffer, 500, kCFStringEncodingASCII ) ) 42 | return std::string( buffer ); 43 | } 44 | 45 | return ""; 46 | } 47 | 48 | CFStringRef cfStr = nullptr; 49 | }; 50 | 51 | std::string NativeOSManager::GetHardwareProperties( const Version& hidVersion ) 52 | { 53 | HIDLog::Write( "Получаем данные о железе в среде MAC", LogLevel::Debug ); 54 | std::string result = ""; 55 | 56 | result += GetIOPlatformProperty( "IOPlatformSerialNumber" ); 57 | result += GetIOPlatformProperty( "IOPlatformUUID" ); 58 | result += GetIONetworkProperty( "IOMACAddress" ); 59 | result += GetIOStorageProperty( "Serial Number" ); 60 | 61 | return result; 62 | } 63 | 64 | std::string NativeOSManager::GetIOPlatformProperty( const std::string& property ) 65 | { 66 | std::string result = ""; 67 | CFStringWrapper propertyCF( property ); 68 | 69 | io_service_t service = IOServiceGetMatchingService( 0, IOServiceMatching( "IOPlatformExpertDevice" ) ); 70 | 71 | if( service ) 72 | { 73 | CFTypeRef registryPropertyVoidCF = IORegistryEntryCreateCFProperty( service, propertyCF.cfStr, 0, 0 ); 74 | CFStringWrapper registryPropertyCF( ( CFStringRef )registryPropertyVoidCF ); 75 | 76 | result = registryPropertyCF.GetStdString(); 77 | IOObjectRelease( service ); 78 | } 79 | 80 | HIDLog::Write( "Свойство \'" + property + "\' сервиса \'IOPlatformExpertDevice\'" 81 | " = \'" + result + "\'", LogLevel::Debug ); 82 | return result; 83 | } 84 | 85 | std::string NativeOSManager::GetIONetworkProperty( const std::string &property ) 86 | { 87 | std::string result = ""; 88 | CFStringWrapper propertyCF( property ); 89 | 90 | io_service_t service = IOServiceGetMatchingService( 91 | kIOMasterPortDefault, IOServiceMatching( "IOEthernetInterface" ) ); 92 | 93 | if( service ) 94 | { 95 | CFTypeRef registryPropertyVoidCF = IORegistryEntryCreateCFProperty( service, propertyCF.cfStr, 0, 0 ); 96 | 97 | const size_t MACAddressLength = 6; 98 | CFDataRef registryData = ( CFDataRef )registryPropertyVoidCF; 99 | uint8_t MACAddrBuffer[ MACAddressLength ]; 100 | CFDataGetBytes( registryData, { .location = 0, .length = MACAddressLength }, MACAddrBuffer ); 101 | 102 | std::ostringstream ss; 103 | for( int i = 0; i < MACAddressLength; i++ ) 104 | { 105 | if( i != 0 ) ss << ":"; 106 | ss.width( 2 ); 107 | ss.fill( '0' ); 108 | ss << std::hex << ( int )( MACAddrBuffer[ i ] ); 109 | } 110 | 111 | result = ss.str(); 112 | 113 | CFRelease( registryPropertyVoidCF ); 114 | IOObjectRelease( service ); 115 | } 116 | 117 | HIDLog::Write( "Свойство \'" + property + "\' сервиса \'IOEthernetInterface\'" 118 | " = \'" + result + "\'", LogLevel::Debug ); 119 | return result; 120 | } 121 | 122 | std::string NativeOSManager::GetIOStorageProperty( const std::string &property ) 123 | { 124 | std::string result = ""; 125 | CFStringWrapper propertyCF( property ); 126 | 127 | io_service_t service = IOServiceGetMatchingService( 128 | kIOMasterPortDefault, IOServiceMatching( "IOAHCIBlockStorageDevice" ) ); 129 | 130 | if( service ) 131 | { 132 | CFMutableDictionaryRef properties = nullptr; 133 | IORegistryEntryCreateCFProperties( service, &properties, 0, 0 ); 134 | CFRetain( properties ); // lock properties (Без блокирования коллекции 135 | // может быть ошибка несинхронизированного доступа к коллекции) 136 | 137 | CFDictionaryRef deviceProperties = ( CFDictionaryRef )( CFDictionaryGetValue( properties, CFSTR( "Device Characteristics" ) ) ); 138 | CFRetain( deviceProperties ); // lock deviceProperties 139 | 140 | CFStringWrapper serialNumber( ( CFStringRef )( CFDictionaryGetValue( deviceProperties, propertyCF.cfStr ) ) ); 141 | result = serialNumber.GetStdString(); 142 | 143 | CFRelease( deviceProperties ); 144 | CFRelease( properties ); 145 | IOObjectRelease( service ); 146 | } 147 | 148 | HIDLog::Write( "Свойство \'Serial Number\' сервиса \'IOAHCIBlockStorageDevice\'" 149 | " = \'" + result + "\'", LogLevel::Debug ); 150 | return result; 151 | } 152 | 153 | } // end namespace system_info 154 | -------------------------------------------------------------------------------- /implementation/windows/windows_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "windows_manager.hpp" 2 | #include "../log.hpp" 3 | #include "../util.hpp" 4 | #include "../version.hpp" 5 | 6 | // Windows-specific include 7 | #include 8 | #include 9 | 10 | // Standart include 11 | #include 12 | 13 | namespace system_info 14 | { 15 | 16 | struct BSTRHolder 17 | { 18 | BSTRHolder( const wchar_t* str ) 19 | { 20 | bstr = SysAllocString( str ); 21 | } 22 | 23 | ~BSTRHolder() 24 | { 25 | if( bstr ) 26 | SysFreeString( bstr ); 27 | } 28 | 29 | BSTR bstr; 30 | }; 31 | 32 | // В mingw CLSID_WbemLocator и IID_IWbemLocator выдают undefined reference, используем свой "аналог" 33 | const CLSID NativeOSManager::local_CLSID_WbemLocator = { 0x4590F811, 0x1D3A, 0x11D0, { 0x89, 0x1F, 0, 0xAA, 0, 0x4B, 0x2E, 0x24 } }; 34 | const IID NativeOSManager::local_IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf, { 0x88, 0x4d, 0, 0xAA, 0, 0x4B, 0x2E, 0x24 } }; 35 | 36 | // version пока не используем 37 | std::string NativeOSManager::GetHardwareProperties( const Version& version ) 38 | { 39 | HIDLog::Write( "Получаем данные о железе в среде Windows", LogLevel::Debug ); 40 | std::wstring hardwareId = L""; 41 | 42 | if( SUCCEEDED( CoInitialize( nullptr ) ) ) 43 | { 44 | hardwareId = GetWmiProperties( version ); 45 | CoUninitialize(); 46 | } 47 | 48 | return Util::WstringToString( hardwareId ); 49 | } 50 | 51 | std::wstring NativeOSManager::GetWmiProperties( const Version& version ) 52 | { 53 | std::wstring result; 54 | //CoInitializeSecurity 55 | 56 | IWbemLocator* locator; 57 | if( SUCCEEDED( CoCreateInstance( local_CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, local_IID_IWbemLocator, reinterpret_cast< void** >( &locator ) ) ) ) 58 | { 59 | IWbemServices* services; 60 | BSTRHolder net( L"ROOT\\CIMV2" ); 61 | if( SUCCEEDED( locator->ConnectServer( net.bstr, nullptr, nullptr, nullptr, WBEM_FLAG_CONNECT_USE_MAX_WAIT, nullptr, nullptr, &services ) ) ) 62 | { 63 | if( SUCCEEDED( CoSetProxyBlanket( services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE ) ) ) 64 | { 65 | try 66 | { 67 | if( version <= Version( "1.3" ) ) 68 | { 69 | result += GetWmiProperty( services, L"Win32_ComputerSystemProduct", L"UUID" ); 70 | result += GetWmiProperty( services, L"Win32_OperatingSystem", L"SerialNumber" ); 71 | } 72 | result += GetWmiPropertyForHdd( services, version >= Version( "1.2" ) ); 73 | result += GetWmiProperty( services, L"Win32_ComputerSystemProduct", L"IdentifyingNumber" ); 74 | result += GetWmiProperty( services, L"Win32_BaseBoard", L"SerialNumber" ); 75 | if( version > Version( "1.0" ) ) 76 | result += GetWmiPropertyForNetworkAdapter( services ); 77 | } 78 | catch( ... ) 79 | { 80 | result.clear(); 81 | } 82 | } 83 | services->Release(); 84 | } 85 | locator->Release(); 86 | } 87 | 88 | return result; 89 | } 90 | 91 | std::wstring NativeOSManager::GetWmiProperty( IWbemServices* services, const wchar_t* classname, const wchar_t* property, bool check ) 92 | { 93 | std::wstring result; 94 | IEnumWbemClassObject* enumerator = nullptr; 95 | try 96 | { 97 | std::wstring query = L"SELECT * FROM "; 98 | query += classname; 99 | BSTRHolder query_holder( query.c_str() ); 100 | BSTRHolder lang( L"WQL" ); 101 | if( SUCCEEDED( services->ExecQuery( lang.bstr, query_holder.bstr, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &enumerator ) ) ) 102 | { 103 | IWbemClassObject* object; 104 | ULONG returned = 0; 105 | if( SUCCEEDED( enumerator->Next( WBEM_INFINITE, 1, &object, &returned ) ) && ( returned > 0 ) ) 106 | { 107 | VARIANT value; 108 | CIMTYPE type; 109 | if( SUCCEEDED( object->Get( property, 0, &value, &type, nullptr ) ) ) 110 | { 111 | if( ( type == CIM_STRING ) && ( value.vt == VT_BSTR ) ) 112 | result += ProcessWmiProperty( V_BSTR( &value ), check ); 113 | 114 | HIDLog::Write( std::wstring() + L"WMI property \"" + property + L"\" FOR CLASS \"" + 115 | classname + L"\" = \"" + result + L"\"", LogLevel::Debug ); 116 | VariantClear( &value ); 117 | } 118 | object->Release(); 119 | } 120 | } 121 | } 122 | catch( ... ) 123 | { 124 | result.clear(); 125 | } 126 | 127 | if( enumerator ) 128 | enumerator->Release(); 129 | 130 | return result; 131 | } 132 | 133 | std::wstring NativeOSManager::GetWmiPropertyForHdd( IWbemServices* services, bool check ) 134 | { 135 | std::wstring from = L"win32_logicaldisk WHERE deviceid=\""; 136 | PWSTR location; 137 | if( SUCCEEDED( SHGetKnownFolderPath( FOLDERID_System, KF_FLAG_DONT_UNEXPAND, nullptr, &location ) ) ) 138 | { 139 | from.append( 1, *location ); 140 | from.append( L":\"" ); 141 | CoTaskMemFree( location ); 142 | return GetWmiProperty( services, from.c_str(), L"VolumeSerialNumber", check ); 143 | } 144 | 145 | HIDLog::Write( "Идентификатор раздела жесткого диска не удалось получить", LogLevel::Debug ); 146 | return std::wstring(); 147 | } 148 | 149 | std::wstring NativeOSManager::ProcessWmiProperty( BSTR prop, bool check ) 150 | { 151 | std::wstring value( prop, SysStringLen( prop ) ); 152 | ToLower( value ); 153 | // Внимание: все константы в нижнем регистре 154 | const std::wstring empty_guid( L"00000000-0000-0000-0000-000000000000" ); 155 | const std::wstring broken_guid( L"ffffffff-ffff-ffff-ffff-ffffffffffff" ); 156 | const std::wstring empty_oem( L"to be filled by o.e.m." ); 157 | 158 | if( check ) 159 | { 160 | if( ( value == empty_guid ) || ( value == broken_guid ) || ( value == empty_oem ) ) 161 | { 162 | return std::wstring(); 163 | } 164 | } 165 | 166 | return value; 167 | } 168 | 169 | std::wstring NativeOSManager::GetWmiPropertyForNetworkAdapter( IWbemServices* services ) 170 | { 171 | return GetWmiProperty( services, L"Win32_NetworkAdapter WHERE Manufacturer != \'Microsoft\' AND NOT PNPDeviceID LIKE \'ROOT%\\\\\'", L"MACAddress", false ); 172 | } 173 | 174 | void NativeOSManager::ToLower( std::wstring& string ) 175 | { 176 | std::transform( string.begin(), string.end(), string.begin(), tolower ); 177 | } 178 | 179 | } // end namespace system_info 180 | -------------------------------------------------------------------------------- /implementation/md5.cpp: -------------------------------------------------------------------------------- 1 | #include "md5.hpp" 2 | 3 | #include 4 | 5 | namespace system_info 6 | { 7 | 8 | static const int S11 = 7; 9 | static const int S12 = 12; 10 | static const int S13 = 17; 11 | static const int S14 = 22; 12 | static const int S21 = 5; 13 | static const int S22 = 9; 14 | static const int S23 = 14; 15 | static const int S24 = 20; 16 | static const int S31 = 4; 17 | static const int S32 = 11; 18 | static const int S33 = 16; 19 | static const int S34 = 23; 20 | static const int S41 = 6; 21 | static const int S42 = 10; 22 | static const int S43 = 15; 23 | static const int S44 = 21; 24 | 25 | inline std::uint32_t MD5::F( std::uint32_t x, std::uint32_t y, std::uint32_t z ) 26 | { 27 | return ( x & y ) | ( ~x & z ); 28 | } 29 | 30 | inline std::uint32_t MD5::G( std::uint32_t x, std::uint32_t y, std::uint32_t z ) 31 | { 32 | return ( x & z ) | ( y & ~z ); 33 | } 34 | 35 | inline std::uint32_t MD5::H( std::uint32_t x, std::uint32_t y, std::uint32_t z ) 36 | { 37 | return x ^ y ^ z; 38 | } 39 | 40 | inline std::uint32_t MD5::I( std::uint32_t x, std::uint32_t y, std::uint32_t z ) 41 | { 42 | return y ^ ( x | ~z ); 43 | } 44 | 45 | inline std::uint32_t MD5::RotateLeft( std::uint32_t x, int n ) 46 | { 47 | return ( x << n ) | ( x >> ( 32 - n ) ); 48 | } 49 | 50 | inline void MD5::FF( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, 51 | std::uint32_t s, std::uint32_t ac ) 52 | { 53 | a = RotateLeft( a + F( b, c, d ) + x + ac, s ) + b; 54 | } 55 | 56 | inline void MD5::GG( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, 57 | std::uint32_t s, std::uint32_t ac ) 58 | { 59 | a = RotateLeft( a + G( b, c, d ) + x + ac, s ) + b; 60 | } 61 | 62 | inline void MD5::HH( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, 63 | std::uint32_t s, std::uint32_t ac ) 64 | { 65 | a = RotateLeft( a + H( b, c, d ) + x + ac, s ) + b; 66 | } 67 | 68 | inline void MD5::II( std::uint32_t& a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, 69 | std::uint32_t s, std::uint32_t ac ) 70 | { 71 | a = RotateLeft( a + I( b, c, d ) + x + ac, s ) + b; 72 | } 73 | 74 | 75 | MD5::MD5() 76 | { 77 | Init(); 78 | } 79 | 80 | MD5::MD5( const std::string& text ) 81 | { 82 | Init(); 83 | Update( text.data(), text.size() ); 84 | Finalize(); 85 | } 86 | 87 | void MD5::Init() 88 | { 89 | finalized = false; 90 | 91 | count[ 0 ] = 0; 92 | count[ 1 ] = 0; 93 | 94 | // load magic initialization constants. 95 | state[ 0 ] = 0x67452301; 96 | state[ 1 ] = 0xefcdab89; 97 | state[ 2 ] = 0x98badcfe; 98 | state[ 3 ] = 0x10325476; 99 | } 100 | 101 | void MD5::Decode( std::uint32_t output[], const std::uint8_t input[], std::uint32_t len ) 102 | { 103 | for( unsigned int i = 0, j = 0; j < len; i++, j += 4 ) 104 | output[ i ] = ( ( std::uint32_t )input[ j ] ) | ( ( ( std::uint32_t )input[ j + 1 ] ) << 8 ) | 105 | ( ( ( std::uint32_t )input[ j + 2 ] ) << 16 ) | ( ( ( std::uint32_t )input[ j + 3 ] ) << 24 ); 106 | } 107 | 108 | void MD5::Encode( std::uint8_t output[], const std::uint32_t input[], std::uint32_t len ) 109 | { 110 | for( std::uint32_t i = 0, j = 0; j < len; i++, j += 4 ) 111 | { 112 | output[ j ] = input[ i ] & 0xff; 113 | output[ j + 1 ] = ( input[ i ] >> 8 ) & 0xff; 114 | output[ j + 2 ] = ( input[ i ] >> 16 ) & 0xff; 115 | output[ j + 3 ] = ( input[ i ] >> 24 ) & 0xff; 116 | } 117 | } 118 | 119 | void MD5::Transform( const std::uint8_t block[ blocksize ] ) 120 | { 121 | std::uint32_t a = state[ 0 ], b = state[ 1 ], c = state[ 2 ], d = state[ 3 ], x[ 16 ]; 122 | Decode( x, block, blocksize ); 123 | 124 | /* Round 1 */ 125 | FF( a, b, c, d, x[ 0 ], S11, 0xd76aa478 ); /* 1 */ 126 | FF( d, a, b, c, x[ 1 ], S12, 0xe8c7b756 ); /* 2 */ 127 | FF( c, d, a, b, x[ 2 ], S13, 0x242070db ); /* 3 */ 128 | FF( b, c, d, a, x[ 3 ], S14, 0xc1bdceee ); /* 4 */ 129 | FF( a, b, c, d, x[ 4 ], S11, 0xf57c0faf ); /* 5 */ 130 | FF( d, a, b, c, x[ 5 ], S12, 0x4787c62a ); /* 6 */ 131 | FF( c, d, a, b, x[ 6 ], S13, 0xa8304613 ); /* 7 */ 132 | FF( b, c, d, a, x[ 7 ], S14, 0xfd469501 ); /* 8 */ 133 | FF( a, b, c, d, x[ 8 ], S11, 0x698098d8 ); /* 9 */ 134 | FF( d, a, b, c, x[ 9 ], S12, 0x8b44f7af ); /* 10 */ 135 | FF( c, d, a, b, x[ 10 ], S13, 0xffff5bb1 ); /* 11 */ 136 | FF( b, c, d, a, x[ 11 ], S14, 0x895cd7be ); /* 12 */ 137 | FF( a, b, c, d, x[ 12 ], S11, 0x6b901122 ); /* 13 */ 138 | FF( d, a, b, c, x[ 13 ], S12, 0xfd987193 ); /* 14 */ 139 | FF( c, d, a, b, x[ 14 ], S13, 0xa679438e ); /* 15 */ 140 | FF( b, c, d, a, x[ 15 ], S14, 0x49b40821 ); /* 16 */ 141 | 142 | /* Round 2 */ 143 | GG( a, b, c, d, x[ 1 ], S21, 0xf61e2562 ); /* 17 */ 144 | GG( d, a, b, c, x[ 6 ], S22, 0xc040b340 ); /* 18 */ 145 | GG( c, d, a, b, x[ 11 ], S23, 0x265e5a51 ); /* 19 */ 146 | GG( b, c, d, a, x[ 0 ], S24, 0xe9b6c7aa ); /* 20 */ 147 | GG( a, b, c, d, x[ 5 ], S21, 0xd62f105d ); /* 21 */ 148 | GG( d, a, b, c, x[ 10 ], S22, 0x2441453 ); /* 22 */ 149 | GG( c, d, a, b, x[ 15 ], S23, 0xd8a1e681 ); /* 23 */ 150 | GG( b, c, d, a, x[ 4 ], S24, 0xe7d3fbc8 ); /* 24 */ 151 | GG( a, b, c, d, x[ 9 ], S21, 0x21e1cde6 ); /* 25 */ 152 | GG( d, a, b, c, x[ 14 ], S22, 0xc33707d6 ); /* 26 */ 153 | GG( c, d, a, b, x[ 3 ], S23, 0xf4d50d87 ); /* 27 */ 154 | GG( b, c, d, a, x[ 8 ], S24, 0x455a14ed ); /* 28 */ 155 | GG( a, b, c, d, x[ 13 ], S21, 0xa9e3e905 ); /* 29 */ 156 | GG( d, a, b, c, x[ 2 ], S22, 0xfcefa3f8 ); /* 30 */ 157 | GG( c, d, a, b, x[ 7 ], S23, 0x676f02d9 ); /* 31 */ 158 | GG( b, c, d, a, x[ 12 ], S24, 0x8d2a4c8a ); /* 32 */ 159 | 160 | /* Round 3 */ 161 | HH( a, b, c, d, x[ 5 ], S31, 0xfffa3942 ); /* 33 */ 162 | HH( d, a, b, c, x[ 8 ], S32, 0x8771f681 ); /* 34 */ 163 | HH( c, d, a, b, x[ 11 ], S33, 0x6d9d6122 ); /* 35 */ 164 | HH( b, c, d, a, x[ 14 ], S34, 0xfde5380c ); /* 36 */ 165 | HH( a, b, c, d, x[ 1 ], S31, 0xa4beea44 ); /* 37 */ 166 | HH( d, a, b, c, x[ 4 ], S32, 0x4bdecfa9 ); /* 38 */ 167 | HH( c, d, a, b, x[ 7 ], S33, 0xf6bb4b60 ); /* 39 */ 168 | HH( b, c, d, a, x[ 10 ], S34, 0xbebfbc70 ); /* 40 */ 169 | HH( a, b, c, d, x[ 13 ], S31, 0x289b7ec6 ); /* 41 */ 170 | HH( d, a, b, c, x[ 0 ], S32, 0xeaa127fa ); /* 42 */ 171 | HH( c, d, a, b, x[ 3 ], S33, 0xd4ef3085 ); /* 43 */ 172 | HH( b, c, d, a, x[ 6 ], S34, 0x4881d05 ); /* 44 */ 173 | HH( a, b, c, d, x[ 9 ], S31, 0xd9d4d039 ); /* 45 */ 174 | HH( d, a, b, c, x[ 12 ], S32, 0xe6db99e5 ); /* 46 */ 175 | HH( c, d, a, b, x[ 15 ], S33, 0x1fa27cf8 ); /* 47 */ 176 | HH( b, c, d, a, x[ 2 ], S34, 0xc4ac5665 ); /* 48 */ 177 | 178 | /* Round 4 */ 179 | II( a, b, c, d, x[ 0 ], S41, 0xf4292244 ); /* 49 */ 180 | II( d, a, b, c, x[ 7 ], S42, 0x432aff97 ); /* 50 */ 181 | II( c, d, a, b, x[ 14 ], S43, 0xab9423a7 ); /* 51 */ 182 | II( b, c, d, a, x[ 5 ], S44, 0xfc93a039 ); /* 52 */ 183 | II( a, b, c, d, x[ 12 ], S41, 0x655b59c3 ); /* 53 */ 184 | II( d, a, b, c, x[ 3 ], S42, 0x8f0ccc92 ); /* 54 */ 185 | II( c, d, a, b, x[ 10 ], S43, 0xffeff47d ); /* 55 */ 186 | II( b, c, d, a, x[ 1 ], S44, 0x85845dd1 ); /* 56 */ 187 | II( a, b, c, d, x[ 8 ], S41, 0x6fa87e4f ); /* 57 */ 188 | II( d, a, b, c, x[ 15 ], S42, 0xfe2ce6e0 ); /* 58 */ 189 | II( c, d, a, b, x[ 6 ], S43, 0xa3014314 ); /* 59 */ 190 | II( b, c, d, a, x[ 13 ], S44, 0x4e0811a1 ); /* 60 */ 191 | II( a, b, c, d, x[ 4 ], S41, 0xf7537e82 ); /* 61 */ 192 | II( d, a, b, c, x[ 11 ], S42, 0xbd3af235 ); /* 62 */ 193 | II( c, d, a, b, x[ 2 ], S43, 0x2ad7d2bb ); /* 63 */ 194 | II( b, c, d, a, x[ 9 ], S44, 0xeb86d391 ); /* 64 */ 195 | 196 | state[ 0 ] += a; 197 | state[ 1 ] += b; 198 | state[ 2 ] += c; 199 | state[ 3 ] += d; 200 | 201 | // Zeroize sensitive information. 202 | memset( x, 0, sizeof( x ) ); 203 | } 204 | 205 | void MD5::Update( const unsigned char* input, std::uint32_t length ) 206 | { 207 | // compute number of bytes mod 64 208 | std::uint32_t index = count[ 0 ] / 8 % blocksize; 209 | 210 | // Update number of bits 211 | if( ( count[ 0 ] += ( length << 3 ) ) < ( length << 3 ) ) 212 | count[ 1 ]++; 213 | count[ 1 ] += ( length >> 29 ); 214 | 215 | // number of bytes we need to fill in buffer 216 | std::uint32_t firstpart = 64 - index; 217 | 218 | std::uint32_t i; 219 | 220 | // transform as many times as possible. 221 | if( length >= firstpart ) 222 | { 223 | // fill buffer first, transform 224 | memcpy( &buffer[ index ], input, firstpart ); 225 | Transform( buffer ); 226 | 227 | // transform chunks of blocksize (64 bytes) 228 | for( i = firstpart; i + blocksize <= length; i += blocksize ) 229 | Transform( &input[ i ] ); 230 | 231 | index = 0; 232 | } 233 | else 234 | i = 0; 235 | 236 | // buffer remaining input 237 | memcpy( &buffer[ index ], &input[ i ], length - i ); 238 | } 239 | 240 | void MD5::Update( const char* input, std::uint32_t length ) 241 | { 242 | Update( ( const unsigned char* )input, length ); 243 | } 244 | 245 | MD5& MD5::Finalize() 246 | { 247 | static unsigned char padding[ 64 ] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 250 | 251 | if( !finalized ) 252 | { 253 | // Save number of bits 254 | unsigned char bits[ 8 ]; 255 | Encode( bits, count, 8 ); 256 | 257 | // pad out to 56 mod 64. 258 | std::uint32_t index = count[ 0 ] / 8 % 64; 259 | std::uint32_t padLen = ( index < 56 ) ? ( 56 - index ) : ( 120 - index ); 260 | Update( padding, padLen ); 261 | 262 | // Append length (before padding) 263 | Update( bits, 8 ); 264 | 265 | // Store state in digest 266 | Encode( digest, state, 16 ); 267 | 268 | // Zeroize sensitive information. 269 | memset( buffer, 0, sizeof( buffer ) ); 270 | memset( count, 0, sizeof( count ) ); 271 | 272 | finalized = true; 273 | } 274 | 275 | return *this; 276 | } 277 | 278 | std::string MD5::HexDigest() const 279 | { 280 | if( !finalized ) 281 | return ""; 282 | 283 | char buf[ 33 ]; 284 | for( int i = 0; i < 16; i++ ) 285 | sprintf( buf + i * 2, "%02x", digest[ i ] ); 286 | buf[ 32 ] = 0; 287 | 288 | return std::string( buf ); 289 | } 290 | 291 | } // end namespace system_info 292 | --------------------------------------------------------------------------------