Loading backends/CMakeLists.txt +15 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,21 @@ if(INIPARSER_FOUND) ) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(regeditsrc regconf.cpp) add_library(regedit SHARED ${regeditsrc}) set_target_properties(regedit PROPERTIES PREFIX "" OUTPUT_NAME "regedit.cfg") target_link_libraries(regedit PRIVATE confplus kernel32.lib Advapi32.lib) install(TARGETS regedit RUNTIME DESTINATION bin ) endif() if(NOT YAML_FOUND AND NOT INIPARSER_FOUND) message(ERROR "No backends are found Fatal!") endif() backends/regedit/regedit.cpp +219 −0 Original line number Diff line number Diff line /******************************************************************************* * Copyright (c) 2023, Jan Koester jan.koester@gmx.net * All rights reserved. * * (Lizenzblock beibehalten) *******************************************************************************/ #include <iostream> #include <string> #include <vector> #include <sstream> #include <algorithm> #include <windows.h> #include <winreg.h> #include "regconf.h" // Angenommen: Dies ist der umbenannte yamlconf.h #include "exception.h" // Angenommen: Ihre eigene Exception-Klasse namespace confplus { // Basis-Schlüssel in der Registry. Wir verwenden HKEY_CURRENT_USER // und einen festen Pfad für die Anwendung. const char* REGISTRY_BASE_PATH = "SOFTWARE\\ConfPlus\\Config"; // Hilfsfunktion zum Ersetzen aller Vorkommen eines Substrings (für Pfade) std::string replaceAll(std::string str, const std::string& from, const std::string& to) { size_t start_pos = 0; while((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); } return str; } // Die Klasse wird von Yaml zu Registry umbenannt. class Registry : public BackendApi{ public: const char* getName(); const char* getVersion(); const char* getAuthor(); void loadConfig(const char *path,Config *conf); void saveConfig(const char *path,const Config *conf); Registry(); virtual ~Registry(); }; Registry::Registry(){} Registry::~Registry(){} const char* Registry::getName(){ return "registry"; } const char* Registry::getVersion(){ return "0.1"; } const char* Registry::getAuthor(){ return "Jan Koester"; } /** * @brief Speichert die Konfiguration in der Windows Registry. * * Da das Config-System Pfade wie /Abschnitt/Schlüssel verwendet, * verwenden wir diese als Value-Namen unter dem Basis-Schlüssel. * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet. * @param conf Das Config-Objekt. */ void Registry::saveConfig(const char *path, const Config *conf){ HKEY hKey; DWORD dwDisposition; // Erstellt oder öffnet den Basis-Schlüssel für die Konfiguration LONG lRes = RegCreateKeyExA( HKEY_CURRENT_USER, // Hauptschlüssel REGISTRY_BASE_PATH, // Subkey-Pfad 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, // KEY_WRITE NULL, &hKey, &dwDisposition ); if (lRes != ERROR_SUCCESS) { throw Exception("Failed to create/open registry key."); } // --- Iteration über alle Schlüssel im Config-Objekt --- // Da die Config-API nicht direkt sichtbar ist, simulieren wir die Iteration // und speichern jeden Wert als REG_SZ (String). // Die Iterationslogik müsste hier implementiert werden, um alle // ConfigData* Objekte im Config-Objekt zu erhalten. // Hier ein konzeptionelles Beispiel: std::vector<Config::ConfigData*> allKeys = conf->getAllKeys(); for (Config::ConfigData* ckey : allKeys) { std::string cname = ckey->getPath(); // Z.B. "/Server/Port" std::string cvalue = conf->getValue(ckey, 0); // Hole den 1. Wert // Entferne den führenden Schrägstrich für den Value-Namen if (cname.length() > 0 && cname[0] == '/') { cname = cname.substr(1); } // Speichere den Wert lRes = RegSetValueExA( hKey, cname.c_str(), // Z.B. "Server/Port" 0, REG_SZ, (const BYTE*)cvalue.c_str(), cvalue.length() + 1 ); if (lRes != ERROR_SUCCESS) { std::cerr << "Failed to set value for: " << cname << std::endl; } } // Da die tatsächliche Struktur des Config-Objekts unbekannt ist, // kann hier nur ein Stub eingefügt werden. RegCloseKey(hKey); } /** * @brief Lädt die Konfiguration aus der Windows Registry. * * Liest alle Werte unter dem Basis-Schlüssel und speichert sie im Config-Objekt. * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet. * @param conf Das Config-Objekt. */ void Registry::loadConfig(const char* path, Config* conf) { HKEY hKey; // Öffne den Basis-Schlüssel LONG lRes = RegOpenKeyExA( HKEY_CURRENT_USER, REGISTRY_BASE_PATH, 0, KEY_READ, &hKey ); if (lRes != ERROR_SUCCESS) { // Wenn der Schlüssel nicht existiert, ist das keine Exception, // sondern eine leere Konfiguration. std::cerr << "Registry key not found: " << REGISTRY_BASE_PATH << std::endl; return; } DWORD dwValues; DWORD dwMaxValueNameLen; DWORD dwMaxValueLen; // Ermittelt die Anzahl der Werte und die maximale Länge lRes = RegQueryInfoKey( hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { RegCloseKey(hKey); throw Exception("Failed to query registry key info."); } char* valueNameBuffer = new char[dwMaxValueNameLen + 1]; char* dataBuffer = new char[dwMaxValueLen + 1]; // Fügt 1 für das Null-Terminierungszeichen hinzu DWORD dwSizeValueName = dwMaxValueNameLen + 1; DWORD dwSizeData = dwMaxValueLen + 1; // --- Iteration über alle Values unter dem Basis-Schlüssel --- for (DWORD i = 0; i < dwValues; ++i) { DWORD dwType = 0; dwSizeValueName = dwMaxValueNameLen + 1; dwSizeData = dwMaxValueLen + 1; lRes = RegEnumValueA( hKey, i, valueNameBuffer, &dwSizeValueName, NULL, &dwType, (LPBYTE)dataBuffer, &dwSizeData ); if (lRes == ERROR_SUCCESS) { std::string cname = "/"; cname += std::string(valueNameBuffer); // Z.B. "/Server/Port" std::string cvalue = std::string(dataBuffer); // Unterstützt nur REG_SZ (String) und REG_DWORD (Zahl) if (dwType == REG_SZ) { Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, cvalue); std::cout << "Loading key: " << cname << " Value: " << cvalue << std::endl; } else if (dwType == REG_DWORD) { // Konvertiere DWORD zu String std::stringstream ss; ss << *((DWORD*)dataBuffer); Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, ss.str()); std::cout << "Loading key: " << cname << " Value: " << ss.str() << " (DWORD)" << std::endl; } } else if (lRes == ERROR_NO_MORE_ITEMS) { break; } else { // Fehler beim Lesen des Wertes std::cerr << "Error reading registry value at index " << i << std::endl; } } delete[] valueNameBuffer; delete[] dataBuffer; RegCloseKey(hKey); } } No newline at end of file Loading
backends/CMakeLists.txt +15 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,21 @@ if(INIPARSER_FOUND) ) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(regeditsrc regconf.cpp) add_library(regedit SHARED ${regeditsrc}) set_target_properties(regedit PROPERTIES PREFIX "" OUTPUT_NAME "regedit.cfg") target_link_libraries(regedit PRIVATE confplus kernel32.lib Advapi32.lib) install(TARGETS regedit RUNTIME DESTINATION bin ) endif() if(NOT YAML_FOUND AND NOT INIPARSER_FOUND) message(ERROR "No backends are found Fatal!") endif()
backends/regedit/regedit.cpp +219 −0 Original line number Diff line number Diff line /******************************************************************************* * Copyright (c) 2023, Jan Koester jan.koester@gmx.net * All rights reserved. * * (Lizenzblock beibehalten) *******************************************************************************/ #include <iostream> #include <string> #include <vector> #include <sstream> #include <algorithm> #include <windows.h> #include <winreg.h> #include "regconf.h" // Angenommen: Dies ist der umbenannte yamlconf.h #include "exception.h" // Angenommen: Ihre eigene Exception-Klasse namespace confplus { // Basis-Schlüssel in der Registry. Wir verwenden HKEY_CURRENT_USER // und einen festen Pfad für die Anwendung. const char* REGISTRY_BASE_PATH = "SOFTWARE\\ConfPlus\\Config"; // Hilfsfunktion zum Ersetzen aller Vorkommen eines Substrings (für Pfade) std::string replaceAll(std::string str, const std::string& from, const std::string& to) { size_t start_pos = 0; while((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); } return str; } // Die Klasse wird von Yaml zu Registry umbenannt. class Registry : public BackendApi{ public: const char* getName(); const char* getVersion(); const char* getAuthor(); void loadConfig(const char *path,Config *conf); void saveConfig(const char *path,const Config *conf); Registry(); virtual ~Registry(); }; Registry::Registry(){} Registry::~Registry(){} const char* Registry::getName(){ return "registry"; } const char* Registry::getVersion(){ return "0.1"; } const char* Registry::getAuthor(){ return "Jan Koester"; } /** * @brief Speichert die Konfiguration in der Windows Registry. * * Da das Config-System Pfade wie /Abschnitt/Schlüssel verwendet, * verwenden wir diese als Value-Namen unter dem Basis-Schlüssel. * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet. * @param conf Das Config-Objekt. */ void Registry::saveConfig(const char *path, const Config *conf){ HKEY hKey; DWORD dwDisposition; // Erstellt oder öffnet den Basis-Schlüssel für die Konfiguration LONG lRes = RegCreateKeyExA( HKEY_CURRENT_USER, // Hauptschlüssel REGISTRY_BASE_PATH, // Subkey-Pfad 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, // KEY_WRITE NULL, &hKey, &dwDisposition ); if (lRes != ERROR_SUCCESS) { throw Exception("Failed to create/open registry key."); } // --- Iteration über alle Schlüssel im Config-Objekt --- // Da die Config-API nicht direkt sichtbar ist, simulieren wir die Iteration // und speichern jeden Wert als REG_SZ (String). // Die Iterationslogik müsste hier implementiert werden, um alle // ConfigData* Objekte im Config-Objekt zu erhalten. // Hier ein konzeptionelles Beispiel: std::vector<Config::ConfigData*> allKeys = conf->getAllKeys(); for (Config::ConfigData* ckey : allKeys) { std::string cname = ckey->getPath(); // Z.B. "/Server/Port" std::string cvalue = conf->getValue(ckey, 0); // Hole den 1. Wert // Entferne den führenden Schrägstrich für den Value-Namen if (cname.length() > 0 && cname[0] == '/') { cname = cname.substr(1); } // Speichere den Wert lRes = RegSetValueExA( hKey, cname.c_str(), // Z.B. "Server/Port" 0, REG_SZ, (const BYTE*)cvalue.c_str(), cvalue.length() + 1 ); if (lRes != ERROR_SUCCESS) { std::cerr << "Failed to set value for: " << cname << std::endl; } } // Da die tatsächliche Struktur des Config-Objekts unbekannt ist, // kann hier nur ein Stub eingefügt werden. RegCloseKey(hKey); } /** * @brief Lädt die Konfiguration aus der Windows Registry. * * Liest alle Werte unter dem Basis-Schlüssel und speichert sie im Config-Objekt. * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet. * @param conf Das Config-Objekt. */ void Registry::loadConfig(const char* path, Config* conf) { HKEY hKey; // Öffne den Basis-Schlüssel LONG lRes = RegOpenKeyExA( HKEY_CURRENT_USER, REGISTRY_BASE_PATH, 0, KEY_READ, &hKey ); if (lRes != ERROR_SUCCESS) { // Wenn der Schlüssel nicht existiert, ist das keine Exception, // sondern eine leere Konfiguration. std::cerr << "Registry key not found: " << REGISTRY_BASE_PATH << std::endl; return; } DWORD dwValues; DWORD dwMaxValueNameLen; DWORD dwMaxValueLen; // Ermittelt die Anzahl der Werte und die maximale Länge lRes = RegQueryInfoKey( hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { RegCloseKey(hKey); throw Exception("Failed to query registry key info."); } char* valueNameBuffer = new char[dwMaxValueNameLen + 1]; char* dataBuffer = new char[dwMaxValueLen + 1]; // Fügt 1 für das Null-Terminierungszeichen hinzu DWORD dwSizeValueName = dwMaxValueNameLen + 1; DWORD dwSizeData = dwMaxValueLen + 1; // --- Iteration über alle Values unter dem Basis-Schlüssel --- for (DWORD i = 0; i < dwValues; ++i) { DWORD dwType = 0; dwSizeValueName = dwMaxValueNameLen + 1; dwSizeData = dwMaxValueLen + 1; lRes = RegEnumValueA( hKey, i, valueNameBuffer, &dwSizeValueName, NULL, &dwType, (LPBYTE)dataBuffer, &dwSizeData ); if (lRes == ERROR_SUCCESS) { std::string cname = "/"; cname += std::string(valueNameBuffer); // Z.B. "/Server/Port" std::string cvalue = std::string(dataBuffer); // Unterstützt nur REG_SZ (String) und REG_DWORD (Zahl) if (dwType == REG_SZ) { Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, cvalue); std::cout << "Loading key: " << cname << " Value: " << cvalue << std::endl; } else if (dwType == REG_DWORD) { // Konvertiere DWORD zu String std::stringstream ss; ss << *((DWORD*)dataBuffer); Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, ss.str()); std::cout << "Loading key: " << cname << " Value: " << ss.str() << " (DWORD)" << std::endl; } } else if (lRes == ERROR_NO_MORE_ITEMS) { break; } else { // Fehler beim Lesen des Wertes std::cerr << "Error reading registry value at index " << i << std::endl; } } delete[] valueNameBuffer; delete[] dataBuffer; RegCloseKey(hKey); } } No newline at end of file