Loading backends/regedit/regedit.cpp +16 −131 Original line number Diff line number Diff line Loading @@ -100,10 +100,9 @@ namespace confplus { keyStack.pop(); HKEY hKey = currentState.hKey; const std::string& currentConfigPath = currentState.configPath; 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 --- Loading @@ -123,11 +122,9 @@ namespace confplus { 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. // --- 2. Bestimme Puffergrößen und allokiere Puffer --- DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Muss für REG_SZ / REG_DWORD groß genug sein DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); Loading @@ -152,17 +149,11 @@ namespace confplus { } if (lRes != ERROR_SUCCESS) { if (lRes == ERROR_MORE_DATA) { // Ignoriere, wenn Puffer nicht groß genug war (sollte dank RegQueryInfoKeyA nicht passieren) continue; } break; } // ... (Verarbeitung der Werte wie im Original-Code) ... std::string valueNameStr(valueNameBuffer.get()); // Behandlung des leeren Namens (Default Value) if (valueNameStr.empty()) { valueNameStr = "@DEFAULT"; } Loading @@ -175,6 +166,7 @@ namespace confplus { std::string cname = currentConfigPath; size_t pos = 0; bool is_array_index = true; if (valueNameStr != "@DEFAULT") { for (char c : valueNameStr) { if (!std::isdigit(c)) { Loading @@ -195,7 +187,6 @@ namespace confplus { is_array_index = false; } if (!is_array_index) { cname += "/" + valueNameStr; pos = 0; Loading @@ -204,7 +195,6 @@ namespace confplus { 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 @@ -214,7 +204,7 @@ namespace confplus { continue; } } else { continue; // Andere Typen überspringen continue; } if (cvalue.empty()) { Loading @@ -225,21 +215,12 @@ namespace confplus { conf->setValue(ckey, pos, cvalue); } // --- 4. Subkeys (Unterschlüssel) zur Stack hinzufügen --- // Puffergröße für Subkey-Namen bestimmen (NACH RegQueryInfoKeyA) // --- 4. Subkeys (Unterschlüssel) ermitteln und auf den Stack legen --- DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); // Erst alle Subkeys sammeln, um zu prüfen ob alle numerisch sind (sequence-of-mappings) struct SubKeyInfo { HKEY hKey; std::string name; size_t index; }; std::vector<SubKeyInfo> subKeys; bool allNumeric = true; // JEDER Subkey wird nun als nativer, tieferer Ast des Pfad-Baums behandelt. // Keine flache Transponierung mehr, um die Kompatibilität mit Blogis Verzeichnis-Abfragen zu wahren. for (DWORD i = 0; ; ++i) { DWORD dwSizeSubKeyName = maxSubKeySize; Loading @@ -258,121 +239,25 @@ namespace confplus { } std::string subKeyNameStr(subKeyNameBuffer.get()); // Prüfe ob der Subkey-Name rein numerisch ist bool isNumeric = !subKeyNameStr.empty(); for (char c : subKeyNameStr) { if (!std::isdigit(c)) { isNumeric = false; break; } } size_t idx = 0; if (isNumeric) { try { idx = std::stoul(subKeyNameStr); } catch (...) { isNumeric = false; } } if (!isNumeric) { allNumeric = false; if (subKeyNameStr.empty()) { continue; } HKEY hSubKey; lRes = RegOpenKeyExA(hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey); if (lRes == ERROR_SUCCESS) { subKeys.push_back({hSubKey, subKeyNameStr, idx}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } if (!subKeys.empty() && allNumeric) { // Sequence-of-mappings: numerische Subkeys (0, 1, 2...) enthalten // benannte Werte. Transponiere zu parallelen Arrays: // PARENT/0/URL="a", PARENT/1/URL="b" -> PARENT/URL[0]="a", PARENT/URL[1]="b" for (auto& sk : subKeys) { DWORD skValues, skMaxNameLen, skMaxDataLen; lRes = RegQueryInfoKeyA( sk.hKey, NULL, NULL, NULL, NULL, NULL, NULL, &skValues, &skMaxNameLen, &skMaxDataLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { RegCloseKey(sk.hKey); continue; } DWORD skNameSize = skMaxNameLen > 0 ? skMaxNameLen + 1 : 1; DWORD skDataSize = skMaxDataLen > 0 ? skMaxDataLen + 1 : 1; std::unique_ptr<char[]> skNameBuf(new char[skNameSize]); std::unique_ptr<char[]> skDataBuf(new char[skDataSize]); for (DWORD v = 0; ; ++v) { DWORD skNameLen = skNameSize; DWORD skDataLen = skDataSize; DWORD skType = 0; lRes = RegEnumValueA( sk.hKey, v, skNameBuf.get(), &skNameLen, NULL, &skType, (LPBYTE)skDataBuf.get(), &skDataLen ); if (lRes == ERROR_NO_MORE_ITEMS) break; if (lRes != ERROR_SUCCESS) break; std::string valName(skNameBuf.get()); if (valName.empty()) continue; std::transform( valName.begin(), valName.end(), valName.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string cvalue; if (skType == REG_SZ || skType == REG_EXPAND_SZ) { cvalue = std::string(skDataBuf.get()); } else if (skType == REG_DWORD) { if (skDataLen >= sizeof(DWORD)) { DWORD dwVal = *reinterpret_cast<DWORD*>(skDataBuf.get()); cvalue = std::to_string(dwVal); } else { continue; } } else { continue; } if (cvalue.empty()) continue; // Speichere als paralleles Array: currentConfigPath/VALUENAME[index] std::string cname = currentConfigPath + "/" + valName; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, sk.index, cvalue); } RegCloseKey(sk.hKey); } } else { // Normale Subkeys: wie bisher zur Stack hinzufügen for (auto& sk : subKeys) { std::string subKeyNameStr = sk.name; std::transform( subKeyNameStr.begin(), subKeyNameStr.end(), subKeyNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string nextConfigPath = currentConfigPath + "/" + subKeyNameStr; keyStack.push({sk.hKey, nextConfigPath, true}); // true: hSubKey wird geschlossen, wenn er vom Stack geholt und verarbeitet wurde keyStack.push({hSubKey, nextConfigPath, true}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } Loading Loading
backends/regedit/regedit.cpp +16 −131 Original line number Diff line number Diff line Loading @@ -100,10 +100,9 @@ namespace confplus { keyStack.pop(); HKEY hKey = currentState.hKey; const std::string& currentConfigPath = currentState.configPath; 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 --- Loading @@ -123,11 +122,9 @@ namespace confplus { 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. // --- 2. Bestimme Puffergrößen und allokiere Puffer --- DWORD maxNameSize = dwMaxValueNameLen > 0 ? dwMaxValueNameLen + 1 : 1; DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; // Muss für REG_SZ / REG_DWORD groß genug sein DWORD maxDataSize = dwMaxValueLen > 0 ? dwMaxValueLen + 1 : 1; std::unique_ptr<char[]> valueNameBuffer(new char[maxNameSize]); std::unique_ptr<char[]> dataBuffer(new char[maxDataSize]); Loading @@ -152,17 +149,11 @@ namespace confplus { } if (lRes != ERROR_SUCCESS) { if (lRes == ERROR_MORE_DATA) { // Ignoriere, wenn Puffer nicht groß genug war (sollte dank RegQueryInfoKeyA nicht passieren) continue; } break; } // ... (Verarbeitung der Werte wie im Original-Code) ... std::string valueNameStr(valueNameBuffer.get()); // Behandlung des leeren Namens (Default Value) if (valueNameStr.empty()) { valueNameStr = "@DEFAULT"; } Loading @@ -175,6 +166,7 @@ namespace confplus { std::string cname = currentConfigPath; size_t pos = 0; bool is_array_index = true; if (valueNameStr != "@DEFAULT") { for (char c : valueNameStr) { if (!std::isdigit(c)) { Loading @@ -195,7 +187,6 @@ namespace confplus { is_array_index = false; } if (!is_array_index) { cname += "/" + valueNameStr; pos = 0; Loading @@ -204,7 +195,6 @@ namespace confplus { 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 @@ -214,7 +204,7 @@ namespace confplus { continue; } } else { continue; // Andere Typen überspringen continue; } if (cvalue.empty()) { Loading @@ -225,21 +215,12 @@ namespace confplus { conf->setValue(ckey, pos, cvalue); } // --- 4. Subkeys (Unterschlüssel) zur Stack hinzufügen --- // Puffergröße für Subkey-Namen bestimmen (NACH RegQueryInfoKeyA) // --- 4. Subkeys (Unterschlüssel) ermitteln und auf den Stack legen --- DWORD maxSubKeySize = dwMaxSubKeyLen > 0 ? dwMaxSubKeyLen + 1 : 1; std::unique_ptr<char[]> subKeyNameBuffer(new char[maxSubKeySize]); // Erst alle Subkeys sammeln, um zu prüfen ob alle numerisch sind (sequence-of-mappings) struct SubKeyInfo { HKEY hKey; std::string name; size_t index; }; std::vector<SubKeyInfo> subKeys; bool allNumeric = true; // JEDER Subkey wird nun als nativer, tieferer Ast des Pfad-Baums behandelt. // Keine flache Transponierung mehr, um die Kompatibilität mit Blogis Verzeichnis-Abfragen zu wahren. for (DWORD i = 0; ; ++i) { DWORD dwSizeSubKeyName = maxSubKeySize; Loading @@ -258,121 +239,25 @@ namespace confplus { } std::string subKeyNameStr(subKeyNameBuffer.get()); // Prüfe ob der Subkey-Name rein numerisch ist bool isNumeric = !subKeyNameStr.empty(); for (char c : subKeyNameStr) { if (!std::isdigit(c)) { isNumeric = false; break; } } size_t idx = 0; if (isNumeric) { try { idx = std::stoul(subKeyNameStr); } catch (...) { isNumeric = false; } } if (!isNumeric) { allNumeric = false; if (subKeyNameStr.empty()) { continue; } HKEY hSubKey; lRes = RegOpenKeyExA(hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey); if (lRes == ERROR_SUCCESS) { subKeys.push_back({hSubKey, subKeyNameStr, idx}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } if (!subKeys.empty() && allNumeric) { // Sequence-of-mappings: numerische Subkeys (0, 1, 2...) enthalten // benannte Werte. Transponiere zu parallelen Arrays: // PARENT/0/URL="a", PARENT/1/URL="b" -> PARENT/URL[0]="a", PARENT/URL[1]="b" for (auto& sk : subKeys) { DWORD skValues, skMaxNameLen, skMaxDataLen; lRes = RegQueryInfoKeyA( sk.hKey, NULL, NULL, NULL, NULL, NULL, NULL, &skValues, &skMaxNameLen, &skMaxDataLen, NULL, NULL ); if (lRes != ERROR_SUCCESS) { RegCloseKey(sk.hKey); continue; } DWORD skNameSize = skMaxNameLen > 0 ? skMaxNameLen + 1 : 1; DWORD skDataSize = skMaxDataLen > 0 ? skMaxDataLen + 1 : 1; std::unique_ptr<char[]> skNameBuf(new char[skNameSize]); std::unique_ptr<char[]> skDataBuf(new char[skDataSize]); for (DWORD v = 0; ; ++v) { DWORD skNameLen = skNameSize; DWORD skDataLen = skDataSize; DWORD skType = 0; lRes = RegEnumValueA( sk.hKey, v, skNameBuf.get(), &skNameLen, NULL, &skType, (LPBYTE)skDataBuf.get(), &skDataLen ); if (lRes == ERROR_NO_MORE_ITEMS) break; if (lRes != ERROR_SUCCESS) break; std::string valName(skNameBuf.get()); if (valName.empty()) continue; std::transform( valName.begin(), valName.end(), valName.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string cvalue; if (skType == REG_SZ || skType == REG_EXPAND_SZ) { cvalue = std::string(skDataBuf.get()); } else if (skType == REG_DWORD) { if (skDataLen >= sizeof(DWORD)) { DWORD dwVal = *reinterpret_cast<DWORD*>(skDataBuf.get()); cvalue = std::to_string(dwVal); } else { continue; } } else { continue; } if (cvalue.empty()) continue; // Speichere als paralleles Array: currentConfigPath/VALUENAME[index] std::string cname = currentConfigPath + "/" + valName; Config::ConfigData* ckey = conf->setKey(cname); conf->setValue(ckey, sk.index, cvalue); } RegCloseKey(sk.hKey); } } else { // Normale Subkeys: wie bisher zur Stack hinzufügen for (auto& sk : subKeys) { std::string subKeyNameStr = sk.name; std::transform( subKeyNameStr.begin(), subKeyNameStr.end(), subKeyNameStr.begin(), [](unsigned char c){ return std::toupper(c); } ); std::string nextConfigPath = currentConfigPath + "/" + subKeyNameStr; keyStack.push({sk.hKey, nextConfigPath, true}); // true: hSubKey wird geschlossen, wenn er vom Stack geholt und verarbeitet wurde keyStack.push({hSubKey, nextConfigPath, true}); } else { std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() << " in " << currentConfigPath << ". Error: " << lRes << std::endl; } } Loading