Loading backends/regedit/regedit.cpp +121 −39 Original line number Diff line number Diff line Loading @@ -88,10 +88,11 @@ namespace confplus { * Verwendet einen Stack anstelle von Rekursion. */ void Registry::loadsubKey(Config* conf, HKEY hRootKey, const std::string& rootConfigPath) { std::cout << "[DEBUG] Entering loadsubKey. Root Path: " << rootConfigPath << std::endl; std::stack<KeyState> keyStack; keyStack.push({hRootKey, rootConfigPath, false}); // Initialisiere den Stack mit dem Startschlüssel. keyStack.push({hRootKey, rootConfigPath, false}); // false: hRootKey wird in loadConfig geschlossen while (!keyStack.empty()) { KeyState currentState = keyStack.top(); Loading @@ -101,19 +102,42 @@ namespace confplus { const std::string& currentConfigPath = currentState.configPath; LONG lRes; // WICHTIG: Die DWORDs müssen deklariert werden DWORD dwValues, dwSubKeys, dwMaxValueNameLen, dwMaxValueLen, dwMaxSubKeyLen; // --- 1. Hole Infos über den aktuellen Schlüssel --- lRes = RegQueryInfoKeyA( hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxSubKeyLen, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { std::cerr << "[DEBUG] RegQueryInfoKeyA failed for " << currentConfigPath << ". Error: " << lRes << std::endl; if (currentState.closeHandle) { RegCloseKey(hKey); } continue; } // --- 2. Bestimme Puffergrößen und allokiere Puffer (NACH RegQueryInfoKeyA) --- // Die max-Längen sind die Zeichenanzahl, daher +1 für das Null-Terminierungszeichen. // Wenn die Registry-Datenbank keine Längen bereitstellt, Standardgröße 1 verwenden. DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Muss für REG_SZ / REG_DWORD groß genug sein std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); DWORD dwSizeValueName, dwSizeData, dwType; // --- 3. Werte (Values) laden --- for (DWORD i = 0; ; ++i) { dwType = 0; dwSizeValueName = maxNameSize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden dwSizeData = maxDataSize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden dwSizeValueName = maxNameSize; dwSizeData = maxDataSize; lRes = RegEnumValueA( hKey, i, Loading @@ -123,23 +147,37 @@ namespace confplus { ); if (lRes == ERROR_NO_MORE_ITEMS) { break; // Korrekte Terminierung break; } if (lRes != ERROR_SUCCESS) { if (lRes == ERROR_MORE_DATA) { // Ignoriere, wenn Puffer nicht groß genug war (sollte dank RegQueryInfoKeyA nicht passieren) continue; } break; } // Guaranteed ERROR_SUCCESS // ... (Verarbeitung der Werte wie im Original-Code) ... std::string valueNameStr(valueNameBuffer.get()); std::string cname = currentConfigPath; std::string cvalue; if (!valueNameStr.empty()) { cname += "/" + valueNameStr; // Behandlung des leeren Namens (Default Value) if (valueNameStr.empty()) { valueNameStr = "@DEFAULT"; } if (dwType == REG_SZ) { std::transform( valueNameStr.begin(), valueNameStr.end(), valueNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string cname = currentConfigPath; cname += "/" + valueNameStr; std::string cvalue; if (dwType == REG_SZ || dwType == REG_EXPAND_SZ) { // Ensure null termination for string types, although RegEnumValueA should handle it cvalue = std::string(dataBuffer.get()); } else if (dwType == REG_DWORD) { if (dwSizeData >= sizeof(DWORD)) { Loading @@ -149,25 +187,27 @@ namespace confplus { continue; } } else { continue; continue; // Andere Typen überspringen } if (cvalue.empty()) { continue; } std::transform(cname.begin(), cname.end(), cname.begin(), [](unsigned char c){ return std::toupper(c); } ); std::cout << "[DEBUG] Registry Key: " << cname << " = " << cvalue << std::endl; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, cvalue); } // --- 4. Subkeys (Unterschlüssel) zur Stack hinzufügen --- // Puffergröße für Subkey-Namen bestimmen (NACH RegQueryInfoKeyA) DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); for (DWORD i = 0; ; ++i) { DWORD dwSizeSubKeyName = maxSubKeySize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden DWORD dwSizeSubKeyName = maxSubKeySize; lRes = RegEnumKeyExA( hKey, i, Loading @@ -176,26 +216,39 @@ namespace confplus { ); if (lRes == ERROR_NO_MORE_ITEMS) { break; // Korrekte Terminierung, springt zum nächsten KeyState break; } if (lRes != ERROR_SUCCESS) { // Wenn ein Fehler auftritt, beenden wir die Subkey-Iteration für diesen Schlüssel zur Sicherheit. break; } // Guaranteed ERROR_SUCCESS HKEY hSubKey; // RegOpenKeyExA erfordert keinen KEY_WOW64_64KEY hier, da der Handle hKey bereits die richtige Ansicht hat. lRes = RegOpenKeyExA(hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey); if (lRes == ERROR_SUCCESS) { std::string subKeyNameStr(subKeyNameBuffer.get()); std::transform( subKeyNameStr.begin(), subKeyNameStr.end(), subKeyNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string nextConfigPath = currentConfigPath + "/" + subKeyNameStr; // Debug-Ausgabe für den Stack-Push std::cout << "[DEBUG] Pushing Stack: " << nextConfigPath << std::endl; keyStack.push({hSubKey, nextConfigPath, true}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } // Den Handle des aktuellen Zustands schließen // --- 5. Den Handle des aktuellen Zustands schließen --- if (currentState.closeHandle) { RegCloseKey(hKey); } Loading Loading @@ -368,19 +421,42 @@ namespace confplus { * @brief Lädt die Konfiguration aus der Windows Registry. * NEUE LOGIK: Parst den vollen Pfad (z.B. HKEY_LOCAL_MACHINE\SOFTWARE). */ // In regedit.cpp / Registry::loadConfig void Registry::loadConfig(const char* path, Config* conf) { std::string fullPath(path); HKEY hRootKey = HKEY_CURRENT_USER; // Standard-Root-Key HKEY hRootKey = HKEY_CURRENT_USER; // --- 1. Konfigurationspfad speichern (mit Forward Slashes) --- std::string initialConfigPath = fullPath; std::replace(initialConfigPath.begin(), initialConfigPath.end(), '\\', '/'); if (initialConfigPath.empty() || initialConfigPath[0] != '/') { initialConfigPath.insert(0, 1, '/'); } // --- 2. fullPath für Registry API vorbereiten (Backslashes) --- // Ersetze Forward Slashes durch EIN Backslash. std::replace(fullPath.begin(), fullPath.end(), '/', '\\'); // Entferne führenden Backslash, falls vorhanden, zur korrekten Root-Key-Erkennung if (!fullPath.empty() && fullPath[0] == '\\') { fullPath.erase(0, 1); } std::string subKeyPath = fullPath; // 1. Root-Key und Subkey-Pfad parsen // 3. 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 // KORREKTUR: Normalisierung des Root Key Namens std::transform(rootKeyName.begin(), rootKeyName.end(), rootKeyName.begin(), [](unsigned char c){ return std::toupper(c); }); // Konvertierung der Root-Key-Namen (nun Case-Insensitive) if (rootKeyName == "HKEY_LOCAL_MACHINE" || rootKeyName == "HKLM") { hRootKey = HKEY_LOCAL_MACHINE; } else if (rootKeyName == "HKEY_CURRENT_USER" || rootKeyName == "HKCU") { Loading @@ -392,38 +468,44 @@ namespace confplus { } 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 '\' // KORREKTUR: Subkey-Pfad ist der Rest nach dem EINEN '\' (slashPos + 1) subKeyPath = fullPath.substr(slashPos + 1); } OpenKey: HKEY hKey; REGSAM accessRights = KEY_READ; // KORREKTUR (FIX für Error 161): Erzwinge 64-Bit-Ansicht für HKLM und HKU if (hRootKey == HKEY_LOCAL_MACHINE || hRootKey == HKEY_USERS) { accessRights |= KEY_WOW64_64KEY; } // Öffne den Hauptschlüssel LONG lRes = RegOpenKeyExA( hRootKey, // Der ermittelte Root-Key subKeyPath.c_str(), // Der Subkey-Pfad relativ zum Root-Key hRootKey, subKeyPath.c_str(), // Nur "SOFTWARE" 0, KEY_READ, accessRights, // KEY_READ | KEY_WOW64_64KEY &hKey ); if (lRes != ERROR_SUCCESS) { std::cerr << "Registry key not found: " << fullPath << " (Error: " << lRes << ")" << std::endl; // Ausgabe des Subkey-Pfades, der gescheitert ist (z.B. "SOFTWARE") std::cerr << "Registry key not found: " << subKeyPath << " (Error: " << lRes << ")" << std::endl; return; } // Starte die rekursive Ladefunktion. loadsubKey(conf, hKey, ""); // Starte die iterative Ladefunktion mit dem vollständigen Pfad. loadsubKey(conf, hKey, initialConfigPath); RegCloseKey(hKey); } } }; // --- Implementierung der Export-Funktionen --- EXPORT confplus::BackendApi* create() { Loading Loading
backends/regedit/regedit.cpp +121 −39 Original line number Diff line number Diff line Loading @@ -88,10 +88,11 @@ namespace confplus { * Verwendet einen Stack anstelle von Rekursion. */ void Registry::loadsubKey(Config* conf, HKEY hRootKey, const std::string& rootConfigPath) { std::cout << "[DEBUG] Entering loadsubKey. Root Path: " << rootConfigPath << std::endl; std::stack<KeyState> keyStack; keyStack.push({hRootKey, rootConfigPath, false}); // Initialisiere den Stack mit dem Startschlüssel. keyStack.push({hRootKey, rootConfigPath, false}); // false: hRootKey wird in loadConfig geschlossen while (!keyStack.empty()) { KeyState currentState = keyStack.top(); Loading @@ -101,19 +102,42 @@ namespace confplus { const std::string& currentConfigPath = currentState.configPath; LONG lRes; // WICHTIG: Die DWORDs müssen deklariert werden DWORD dwValues, dwSubKeys, dwMaxValueNameLen, dwMaxValueLen, dwMaxSubKeyLen; // --- 1. Hole Infos über den aktuellen Schlüssel --- lRes = RegQueryInfoKeyA( hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxSubKeyLen, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { std::cerr << "[DEBUG] RegQueryInfoKeyA failed for " << currentConfigPath << ". Error: " << lRes << std::endl; if (currentState.closeHandle) { RegCloseKey(hKey); } continue; } // --- 2. Bestimme Puffergrößen und allokiere Puffer (NACH RegQueryInfoKeyA) --- // Die max-Längen sind die Zeichenanzahl, daher +1 für das Null-Terminierungszeichen. // Wenn die Registry-Datenbank keine Längen bereitstellt, Standardgröße 1 verwenden. DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Muss für REG_SZ / REG_DWORD groß genug sein std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); DWORD dwSizeValueName, dwSizeData, dwType; // --- 3. Werte (Values) laden --- for (DWORD i = 0; ; ++i) { dwType = 0; dwSizeValueName = maxNameSize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden dwSizeData = maxDataSize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden dwSizeValueName = maxNameSize; dwSizeData = maxDataSize; lRes = RegEnumValueA( hKey, i, Loading @@ -123,23 +147,37 @@ namespace confplus { ); if (lRes == ERROR_NO_MORE_ITEMS) { break; // Korrekte Terminierung break; } if (lRes != ERROR_SUCCESS) { if (lRes == ERROR_MORE_DATA) { // Ignoriere, wenn Puffer nicht groß genug war (sollte dank RegQueryInfoKeyA nicht passieren) continue; } break; } // Guaranteed ERROR_SUCCESS // ... (Verarbeitung der Werte wie im Original-Code) ... std::string valueNameStr(valueNameBuffer.get()); std::string cname = currentConfigPath; std::string cvalue; if (!valueNameStr.empty()) { cname += "/" + valueNameStr; // Behandlung des leeren Namens (Default Value) if (valueNameStr.empty()) { valueNameStr = "@DEFAULT"; } if (dwType == REG_SZ) { std::transform( valueNameStr.begin(), valueNameStr.end(), valueNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string cname = currentConfigPath; cname += "/" + valueNameStr; std::string cvalue; if (dwType == REG_SZ || dwType == REG_EXPAND_SZ) { // Ensure null termination for string types, although RegEnumValueA should handle it cvalue = std::string(dataBuffer.get()); } else if (dwType == REG_DWORD) { if (dwSizeData >= sizeof(DWORD)) { Loading @@ -149,25 +187,27 @@ namespace confplus { continue; } } else { continue; continue; // Andere Typen überspringen } if (cvalue.empty()) { continue; } std::transform(cname.begin(), cname.end(), cname.begin(), [](unsigned char c){ return std::toupper(c); } ); std::cout << "[DEBUG] Registry Key: " << cname << " = " << cvalue << std::endl; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, 0, cvalue); } // --- 4. Subkeys (Unterschlüssel) zur Stack hinzufügen --- // Puffergröße für Subkey-Namen bestimmen (NACH RegQueryInfoKeyA) DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); for (DWORD i = 0; ; ++i) { DWORD dwSizeSubKeyName = maxSubKeySize; // WICHTIG: Muss vor jedem Aufruf zurückgesetzt werden DWORD dwSizeSubKeyName = maxSubKeySize; lRes = RegEnumKeyExA( hKey, i, Loading @@ -176,26 +216,39 @@ namespace confplus { ); if (lRes == ERROR_NO_MORE_ITEMS) { break; // Korrekte Terminierung, springt zum nächsten KeyState break; } if (lRes != ERROR_SUCCESS) { // Wenn ein Fehler auftritt, beenden wir die Subkey-Iteration für diesen Schlüssel zur Sicherheit. break; } // Guaranteed ERROR_SUCCESS HKEY hSubKey; // RegOpenKeyExA erfordert keinen KEY_WOW64_64KEY hier, da der Handle hKey bereits die richtige Ansicht hat. lRes = RegOpenKeyExA(hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey); if (lRes == ERROR_SUCCESS) { std::string subKeyNameStr(subKeyNameBuffer.get()); std::transform( subKeyNameStr.begin(), subKeyNameStr.end(), subKeyNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string nextConfigPath = currentConfigPath + "/" + subKeyNameStr; // Debug-Ausgabe für den Stack-Push std::cout << "[DEBUG] Pushing Stack: " << nextConfigPath << std::endl; keyStack.push({hSubKey, nextConfigPath, true}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } // Den Handle des aktuellen Zustands schließen // --- 5. Den Handle des aktuellen Zustands schließen --- if (currentState.closeHandle) { RegCloseKey(hKey); } Loading Loading @@ -368,19 +421,42 @@ namespace confplus { * @brief Lädt die Konfiguration aus der Windows Registry. * NEUE LOGIK: Parst den vollen Pfad (z.B. HKEY_LOCAL_MACHINE\SOFTWARE). */ // In regedit.cpp / Registry::loadConfig void Registry::loadConfig(const char* path, Config* conf) { std::string fullPath(path); HKEY hRootKey = HKEY_CURRENT_USER; // Standard-Root-Key HKEY hRootKey = HKEY_CURRENT_USER; // --- 1. Konfigurationspfad speichern (mit Forward Slashes) --- std::string initialConfigPath = fullPath; std::replace(initialConfigPath.begin(), initialConfigPath.end(), '\\', '/'); if (initialConfigPath.empty() || initialConfigPath[0] != '/') { initialConfigPath.insert(0, 1, '/'); } // --- 2. fullPath für Registry API vorbereiten (Backslashes) --- // Ersetze Forward Slashes durch EIN Backslash. std::replace(fullPath.begin(), fullPath.end(), '/', '\\'); // Entferne führenden Backslash, falls vorhanden, zur korrekten Root-Key-Erkennung if (!fullPath.empty() && fullPath[0] == '\\') { fullPath.erase(0, 1); } std::string subKeyPath = fullPath; // 1. Root-Key und Subkey-Pfad parsen // 3. 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 // KORREKTUR: Normalisierung des Root Key Namens std::transform(rootKeyName.begin(), rootKeyName.end(), rootKeyName.begin(), [](unsigned char c){ return std::toupper(c); }); // Konvertierung der Root-Key-Namen (nun Case-Insensitive) if (rootKeyName == "HKEY_LOCAL_MACHINE" || rootKeyName == "HKLM") { hRootKey = HKEY_LOCAL_MACHINE; } else if (rootKeyName == "HKEY_CURRENT_USER" || rootKeyName == "HKCU") { Loading @@ -392,38 +468,44 @@ namespace confplus { } 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 '\' // KORREKTUR: Subkey-Pfad ist der Rest nach dem EINEN '\' (slashPos + 1) subKeyPath = fullPath.substr(slashPos + 1); } OpenKey: HKEY hKey; REGSAM accessRights = KEY_READ; // KORREKTUR (FIX für Error 161): Erzwinge 64-Bit-Ansicht für HKLM und HKU if (hRootKey == HKEY_LOCAL_MACHINE || hRootKey == HKEY_USERS) { accessRights |= KEY_WOW64_64KEY; } // Öffne den Hauptschlüssel LONG lRes = RegOpenKeyExA( hRootKey, // Der ermittelte Root-Key subKeyPath.c_str(), // Der Subkey-Pfad relativ zum Root-Key hRootKey, subKeyPath.c_str(), // Nur "SOFTWARE" 0, KEY_READ, accessRights, // KEY_READ | KEY_WOW64_64KEY &hKey ); if (lRes != ERROR_SUCCESS) { std::cerr << "Registry key not found: " << fullPath << " (Error: " << lRes << ")" << std::endl; // Ausgabe des Subkey-Pfades, der gescheitert ist (z.B. "SOFTWARE") std::cerr << "Registry key not found: " << subKeyPath << " (Error: " << lRes << ")" << std::endl; return; } // Starte die rekursive Ladefunktion. loadsubKey(conf, hKey, ""); // Starte die iterative Ladefunktion mit dem vollständigen Pfad. loadsubKey(conf, hKey, initialConfigPath); RegCloseKey(hKey); } } }; // --- Implementierung der Export-Funktionen --- EXPORT confplus::BackendApi* create() { Loading