Loading backends/regedit/regedit.cpp +64 −60 Original line number Diff line number Diff line // In regedit.cpp /******************************************************************************* * Copyright (c) 2025, Jan Koester jan.koester@gmx.net * All rights reserved. Loading Loading @@ -27,16 +29,16 @@ #include "regedit.h" #include "exception.h" #include "exception.h" // Angenommener Include #include "conf.h" // Angenommener Include #include <iostream> #include <string> #include <sstream> #include <algorithm> // Für std::replace #include <algorithm> #include <stdexcept> #include <memory> // Für std::unique_ptr #include <memory> // Spezifische Windows API Includes #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winreg.h> Loading @@ -47,18 +49,11 @@ namespace confplus { HKEY REGISTRY_ROOT_KEY = HKEY_CURRENT_USER; // ------------------------------------------------------------------------- // HILFSFUNKTIONEN // HILFSFUNKTIONEN (unverändert) // ------------------------------------------------------------------------- /** * @brief Splittet den Config-Pfad (/Abschnitt/Key) in den Registry Subkey-Pfad (Abschnitt\Key) * und den letzten Teil als Value-Namen. */ void splitConfigPath(const std::string& configPath, std::string& registryKeyPath, std::string& valueName) { // Entferne den führenden '/' std::string path = configPath.length() > 0 && configPath[0] == '/' ? configPath.substr(1) : configPath; // Finde den letzten '/' size_t last_slash = path.rfind('/'); if (last_slash == std::string::npos) { Loading @@ -67,10 +62,13 @@ namespace confplus { } else { registryKeyPath = path.substr(0, last_slash); valueName = path.substr(last_slash + 1); // Ersetze '/' durch '\' für die Registry-API std::replace(registryKeyPath.begin(), registryKeyPath.end(), '/', '\\'); } if (path.find('\\') == std::string::npos) { registryKeyPath = ""; valueName = path; } } bool isInteger(const std::string& s) { Loading @@ -81,14 +79,10 @@ namespace confplus { return it == s.end(); } /** * @brief Rekursive Funktion zum Laden von Werten und Subkeys aus der Registry. */ void loadKeyRecursiveA(Config* conf, HKEY hKey, const std::string& currentConfigPath) { DWORD dwValues, dwSubKeys, dwMaxValueNameLen, dwMaxValueLen, dwMaxSubKeyLen; // 1. Hole Infos über den aktuellen Schlüssel LONG lRes = RegQueryInfoKeyA( hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxSubKeyLen, NULL, Loading @@ -100,13 +94,10 @@ namespace confplus { return; } // --- 2. Werte (Values) laden --- if (dwValues > 0) { // maxNameSize und maxDataSize müssen die Nullterminierung mit einbeziehen DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Verwendung von std::unique_ptr für automatische Speicherverwaltung std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); DWORD dwSizeValueName, dwSizeData, dwType; Loading @@ -125,7 +116,6 @@ namespace confplus { if (lRes == ERROR_SUCCESS) { std::string valueNameStr = std::string(valueNameBuffer.get()); // Überspringe den '(Standardwert)', wenn benannte Werte vorhanden sind if (valueNameStr.empty() && dwValues > 1) { continue; } Loading @@ -144,7 +134,7 @@ namespace confplus { continue; } } else { continue; // Andere Typen ignorieren continue; } Config::ConfigData* ckey = conf->setKey(cname); Loading @@ -153,7 +143,6 @@ namespace confplus { } } // --- 3. Subkeys (Unterschlüssel) rekursiv laden --- if (dwSubKeys > 0) { DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); Loading @@ -169,18 +158,13 @@ namespace confplus { ); if (lRes == ERROR_SUCCESS) { // Öffne den Subkey lRes = RegOpenKeyExA( hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey ); if (lRes == ERROR_SUCCESS) { // Erzeuge den neuen Konfigurationspfad std::string nextConfigPath = currentConfigPath + "/" + std::string(subKeyNameBuffer.get()); // Rekursiver Aufruf loadKeyRecursiveA(conf, hSubKey, nextConfigPath); RegCloseKey(hSubKey); } } Loading Loading @@ -208,32 +192,25 @@ namespace confplus { return "Jan Koester"; } /** * @brief Traversiert die ConfigData-Struktur rekursiv und speichert die Werte. */ void Registry::saveKeyRecursive(HKEY hRootKey, std::string currentPath,const Config::ConfigData* currentData, const Config *conf) { void Registry::saveKeyRecursive(HKEY hRootKey, std::string currentPath, Config::ConfigData* currentData, const Config *conf) { // ... (Die saveKeyRecursive Logik bleibt unverändert, da sie korrekt den globalen REGISTRY_ROOT_KEY verwendet) for (Config::ConfigData* key = currentData; key != nullptr; key = key->nextData.get()) { // Iteriere über die 'nextData'-Kette auf der aktuellen Hierarchie-Ebene for (const Config::ConfigData* key = currentData; key != nullptr; key = key->next()) { std::string localKeyName = key->Key; // ANNAHME: key->Key enthält den lokalen Schlüsselnamen (z.B. "Datenbank", "Port") std::string localKeyName = key->getKey(); if (localKeyName.empty() && !key->childs()) { if (localKeyName.empty() && !key->haveChild) { continue; } std::string subKeyPath = currentPath; std::string valueName = localKeyName; if (key->childs()) { // Sektion/Subkey if (key->haveChild) { if (!subKeyPath.empty()) { subKeyPath += "\\"; } subKeyPath += localKeyName; } else { // Wert if (!subKeyPath.empty()) { subKeyPath += "\\"; } Loading Loading @@ -261,7 +238,7 @@ namespace confplus { if (elements > 1) { currentRegValueName = (valueName.empty() ? "" : valueName + "_") + std::to_string(pos); } else if (valueName.empty()) { currentRegValueName = ""; // (Standardwert) currentRegValueName = ""; } if (isInteger(cvalue)) { Loading @@ -285,37 +262,31 @@ namespace confplus { } } // Schließe den Schlüssel, wenn es nur ein Wert war if (!key->childs() ) { if (!key->haveChild) { RegCloseKey(hSubKey); } } else { std::cerr << "Failed to create subkey: " << subKeyPath << std::endl; } // Rekursiver Aufruf für Child-Knoten if (key->childs()) { if (key->haveChild && key->Child) { std::string nextPath = subKeyPath; if (lRes == ERROR_SUCCESS) { saveKeyRecursive(hRootKey, nextPath, key->getChild(), conf); RegCloseKey(hSubKey); // Schließe nach der Rekursion saveKeyRecursive(hRootKey, nextPath, key->Child.get(), conf); RegCloseKey(hSubKey); } } } } /** * @brief Speichert die Konfiguration in der Windows Registry. */ void Registry::saveConfig(const char *path, const Config *conf){ HKEY hRootKey; DWORD dwDisposition; // Öffne/Erstelle den Hauptschlüssel LONG lRes = RegCreateKeyExA( REGISTRY_ROOT_KEY, REGISTRY_ROOT_KEY, // Nutzt den globalen Root-Key path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, Loading @@ -327,9 +298,8 @@ namespace confplus { throw e[ConfException::Error] << "Failed to create/open root registry key: " << path; } // Starte die rekursive Traversierung if (conf->firstData) { saveKeyRecursive(hRootKey, "", conf->first(), conf); saveKeyRecursive(hRootKey, "", conf->firstData.get(), conf); } RegCloseKey(hRootKey); Loading @@ -337,21 +307,55 @@ namespace confplus { /** * @brief Lädt die Konfiguration aus der Windows Registry. * NEUE LOGIK: Parst den vollen Pfad (z.B. HKEY_LOCAL_MACHINE\SOFTWARE). */ void Registry::loadConfig(const char* path, Config* conf) { std::string fullPath(path); HKEY hRootKey = HKEY_CURRENT_USER; // Standard-Root-Key std::string subKeyPath = fullPath; // 1. Root-Key und Subkey-Pfad parsen size_t slashPos = fullPath.find('\\'); if (slashPos != std::string::npos) { std::string rootKeyName = fullPath.substr(0, slashPos); // Konvertierung der Root-Key-Namen if (rootKeyName == "HKEY_LOCAL_MACHINE" || rootKeyName == "HKLM") { hRootKey = HKEY_LOCAL_MACHINE; } else if (rootKeyName == "HKEY_CURRENT_USER" || rootKeyName == "HKCU") { hRootKey = HKEY_CURRENT_USER; } else if (rootKeyName == "HKEY_CLASSES_ROOT" || rootKeyName == "HKCR") { hRootKey = HKEY_CLASSES_ROOT; } else if (rootKeyName == "HKEY_USERS" || rootKeyName == "HKU") { hRootKey = HKEY_USERS; } else if (rootKeyName == "HKEY_CURRENT_CONFIG" || rootKeyName == "HKCC") { hRootKey = HKEY_CURRENT_CONFIG; } else { // Der Pfad beginnt nicht mit einem bekannten Root-Key. // Behandle den gesamten Pfad als relativ zum Standard-Root-Key (HKEY_CURRENT_USER). goto OpenKey; } // Subkey-Pfad ist der Rest nach dem ersten '\' subKeyPath = fullPath.substr(slashPos + 1); } OpenKey: HKEY hKey; // Öffne den Hauptschlüssel LONG lRes = RegOpenKeyExA( REGISTRY_ROOT_KEY, path, hRootKey, // Der ermittelte Root-Key subKeyPath.c_str(), // Der Subkey-Pfad relativ zum Root-Key 0, KEY_READ, &hKey ); if (lRes != ERROR_SUCCESS) { std::cerr << "Registry key not found: " << path << std::endl; std::cerr << "Registry key not found: " << fullPath << " (Error: " << lRes << ")" << std::endl; return; } Loading Loading
backends/regedit/regedit.cpp +64 −60 Original line number Diff line number Diff line // In regedit.cpp /******************************************************************************* * Copyright (c) 2025, Jan Koester jan.koester@gmx.net * All rights reserved. Loading Loading @@ -27,16 +29,16 @@ #include "regedit.h" #include "exception.h" #include "exception.h" // Angenommener Include #include "conf.h" // Angenommener Include #include <iostream> #include <string> #include <sstream> #include <algorithm> // Für std::replace #include <algorithm> #include <stdexcept> #include <memory> // Für std::unique_ptr #include <memory> // Spezifische Windows API Includes #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winreg.h> Loading @@ -47,18 +49,11 @@ namespace confplus { HKEY REGISTRY_ROOT_KEY = HKEY_CURRENT_USER; // ------------------------------------------------------------------------- // HILFSFUNKTIONEN // HILFSFUNKTIONEN (unverändert) // ------------------------------------------------------------------------- /** * @brief Splittet den Config-Pfad (/Abschnitt/Key) in den Registry Subkey-Pfad (Abschnitt\Key) * und den letzten Teil als Value-Namen. */ void splitConfigPath(const std::string& configPath, std::string& registryKeyPath, std::string& valueName) { // Entferne den führenden '/' std::string path = configPath.length() > 0 && configPath[0] == '/' ? configPath.substr(1) : configPath; // Finde den letzten '/' size_t last_slash = path.rfind('/'); if (last_slash == std::string::npos) { Loading @@ -67,10 +62,13 @@ namespace confplus { } else { registryKeyPath = path.substr(0, last_slash); valueName = path.substr(last_slash + 1); // Ersetze '/' durch '\' für die Registry-API std::replace(registryKeyPath.begin(), registryKeyPath.end(), '/', '\\'); } if (path.find('\\') == std::string::npos) { registryKeyPath = ""; valueName = path; } } bool isInteger(const std::string& s) { Loading @@ -81,14 +79,10 @@ namespace confplus { return it == s.end(); } /** * @brief Rekursive Funktion zum Laden von Werten und Subkeys aus der Registry. */ void loadKeyRecursiveA(Config* conf, HKEY hKey, const std::string& currentConfigPath) { DWORD dwValues, dwSubKeys, dwMaxValueNameLen, dwMaxValueLen, dwMaxSubKeyLen; // 1. Hole Infos über den aktuellen Schlüssel LONG lRes = RegQueryInfoKeyA( hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxSubKeyLen, NULL, Loading @@ -100,13 +94,10 @@ namespace confplus { return; } // --- 2. Werte (Values) laden --- if (dwValues > 0) { // maxNameSize und maxDataSize müssen die Nullterminierung mit einbeziehen DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Verwendung von std::unique_ptr für automatische Speicherverwaltung std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); DWORD dwSizeValueName, dwSizeData, dwType; Loading @@ -125,7 +116,6 @@ namespace confplus { if (lRes == ERROR_SUCCESS) { std::string valueNameStr = std::string(valueNameBuffer.get()); // Überspringe den '(Standardwert)', wenn benannte Werte vorhanden sind if (valueNameStr.empty() && dwValues > 1) { continue; } Loading @@ -144,7 +134,7 @@ namespace confplus { continue; } } else { continue; // Andere Typen ignorieren continue; } Config::ConfigData* ckey = conf->setKey(cname); Loading @@ -153,7 +143,6 @@ namespace confplus { } } // --- 3. Subkeys (Unterschlüssel) rekursiv laden --- if (dwSubKeys > 0) { DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); Loading @@ -169,18 +158,13 @@ namespace confplus { ); if (lRes == ERROR_SUCCESS) { // Öffne den Subkey lRes = RegOpenKeyExA( hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey ); if (lRes == ERROR_SUCCESS) { // Erzeuge den neuen Konfigurationspfad std::string nextConfigPath = currentConfigPath + "/" + std::string(subKeyNameBuffer.get()); // Rekursiver Aufruf loadKeyRecursiveA(conf, hSubKey, nextConfigPath); RegCloseKey(hSubKey); } } Loading Loading @@ -208,32 +192,25 @@ namespace confplus { return "Jan Koester"; } /** * @brief Traversiert die ConfigData-Struktur rekursiv und speichert die Werte. */ void Registry::saveKeyRecursive(HKEY hRootKey, std::string currentPath,const Config::ConfigData* currentData, const Config *conf) { void Registry::saveKeyRecursive(HKEY hRootKey, std::string currentPath, Config::ConfigData* currentData, const Config *conf) { // ... (Die saveKeyRecursive Logik bleibt unverändert, da sie korrekt den globalen REGISTRY_ROOT_KEY verwendet) for (Config::ConfigData* key = currentData; key != nullptr; key = key->nextData.get()) { // Iteriere über die 'nextData'-Kette auf der aktuellen Hierarchie-Ebene for (const Config::ConfigData* key = currentData; key != nullptr; key = key->next()) { std::string localKeyName = key->Key; // ANNAHME: key->Key enthält den lokalen Schlüsselnamen (z.B. "Datenbank", "Port") std::string localKeyName = key->getKey(); if (localKeyName.empty() && !key->childs()) { if (localKeyName.empty() && !key->haveChild) { continue; } std::string subKeyPath = currentPath; std::string valueName = localKeyName; if (key->childs()) { // Sektion/Subkey if (key->haveChild) { if (!subKeyPath.empty()) { subKeyPath += "\\"; } subKeyPath += localKeyName; } else { // Wert if (!subKeyPath.empty()) { subKeyPath += "\\"; } Loading Loading @@ -261,7 +238,7 @@ namespace confplus { if (elements > 1) { currentRegValueName = (valueName.empty() ? "" : valueName + "_") + std::to_string(pos); } else if (valueName.empty()) { currentRegValueName = ""; // (Standardwert) currentRegValueName = ""; } if (isInteger(cvalue)) { Loading @@ -285,37 +262,31 @@ namespace confplus { } } // Schließe den Schlüssel, wenn es nur ein Wert war if (!key->childs() ) { if (!key->haveChild) { RegCloseKey(hSubKey); } } else { std::cerr << "Failed to create subkey: " << subKeyPath << std::endl; } // Rekursiver Aufruf für Child-Knoten if (key->childs()) { if (key->haveChild && key->Child) { std::string nextPath = subKeyPath; if (lRes == ERROR_SUCCESS) { saveKeyRecursive(hRootKey, nextPath, key->getChild(), conf); RegCloseKey(hSubKey); // Schließe nach der Rekursion saveKeyRecursive(hRootKey, nextPath, key->Child.get(), conf); RegCloseKey(hSubKey); } } } } /** * @brief Speichert die Konfiguration in der Windows Registry. */ void Registry::saveConfig(const char *path, const Config *conf){ HKEY hRootKey; DWORD dwDisposition; // Öffne/Erstelle den Hauptschlüssel LONG lRes = RegCreateKeyExA( REGISTRY_ROOT_KEY, REGISTRY_ROOT_KEY, // Nutzt den globalen Root-Key path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, Loading @@ -327,9 +298,8 @@ namespace confplus { throw e[ConfException::Error] << "Failed to create/open root registry key: " << path; } // Starte die rekursive Traversierung if (conf->firstData) { saveKeyRecursive(hRootKey, "", conf->first(), conf); saveKeyRecursive(hRootKey, "", conf->firstData.get(), conf); } RegCloseKey(hRootKey); Loading @@ -337,21 +307,55 @@ namespace confplus { /** * @brief Lädt die Konfiguration aus der Windows Registry. * NEUE LOGIK: Parst den vollen Pfad (z.B. HKEY_LOCAL_MACHINE\SOFTWARE). */ void Registry::loadConfig(const char* path, Config* conf) { std::string fullPath(path); HKEY hRootKey = HKEY_CURRENT_USER; // Standard-Root-Key std::string subKeyPath = fullPath; // 1. Root-Key und Subkey-Pfad parsen size_t slashPos = fullPath.find('\\'); if (slashPos != std::string::npos) { std::string rootKeyName = fullPath.substr(0, slashPos); // Konvertierung der Root-Key-Namen if (rootKeyName == "HKEY_LOCAL_MACHINE" || rootKeyName == "HKLM") { hRootKey = HKEY_LOCAL_MACHINE; } else if (rootKeyName == "HKEY_CURRENT_USER" || rootKeyName == "HKCU") { hRootKey = HKEY_CURRENT_USER; } else if (rootKeyName == "HKEY_CLASSES_ROOT" || rootKeyName == "HKCR") { hRootKey = HKEY_CLASSES_ROOT; } else if (rootKeyName == "HKEY_USERS" || rootKeyName == "HKU") { hRootKey = HKEY_USERS; } else if (rootKeyName == "HKEY_CURRENT_CONFIG" || rootKeyName == "HKCC") { hRootKey = HKEY_CURRENT_CONFIG; } else { // Der Pfad beginnt nicht mit einem bekannten Root-Key. // Behandle den gesamten Pfad als relativ zum Standard-Root-Key (HKEY_CURRENT_USER). goto OpenKey; } // Subkey-Pfad ist der Rest nach dem ersten '\' subKeyPath = fullPath.substr(slashPos + 1); } OpenKey: HKEY hKey; // Öffne den Hauptschlüssel LONG lRes = RegOpenKeyExA( REGISTRY_ROOT_KEY, path, hRootKey, // Der ermittelte Root-Key subKeyPath.c_str(), // Der Subkey-Pfad relativ zum Root-Key 0, KEY_READ, &hKey ); if (lRes != ERROR_SUCCESS) { std::cerr << "Registry key not found: " << path << std::endl; std::cerr << "Registry key not found: " << fullPath << " (Error: " << lRes << ")" << std::endl; return; } Loading