Commit d2aaf69b authored by jan.koester's avatar jan.koester
Browse files

yaml object fix

parent 17c4c3f2
Loading
Loading
Loading
Loading
+176 −10
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <stdexcept>
#include <memory> 
#include <stack>
#include <vector>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -230,6 +231,15 @@ namespace confplus {
            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;
            
            for (DWORD i = 0; ; ++i) {
                DWORD dwSizeSubKeyName = maxSubKeySize;

@@ -247,25 +257,122 @@ namespace confplus {
                    break; 
                }

                // Guaranteed ERROR_SUCCESS
                HKEY hSubKey;
                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;
                    }
                }
                
                // RegOpenKeyExA erfordert keinen KEY_WOW64_64KEY hier, da der Handle hKey bereits die richtige Ansicht hat.
                if (!isNumeric) {
                    allNumeric = false;
                }
                
                HKEY hSubKey;
                lRes = RegOpenKeyExA(hKey, subKeyNameBuffer.get(), 0, KEY_READ, &hSubKey);
                
                if (lRes == ERROR_SUCCESS) {
                    std::string subKeyNameStr(subKeyNameBuffer.get());
                    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(
                        subKeyNameStr.begin(), subKeyNameStr.end(), subKeyNameStr.begin(),
                            valName.begin(), valName.end(), valName.begin(),
                            [](unsigned char c){ return std::toupper(c); }
                        );
                        
                    std::string nextConfigPath = currentConfigPath + "/" + subKeyNameStr;
                        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);
                    }
                    
                    keyStack.push({hSubKey, nextConfigPath, true});
                    RegCloseKey(sk.hKey);
                }
            } else {
                    std::cerr << "[DEBUG] RegOpenKeyExA failed for subkey: " << subKeyNameBuffer.get() 
                            << " in " << currentConfigPath << ". Error: " << lRes << std::endl;
                // 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});
                }
            }

@@ -297,7 +404,6 @@ namespace confplus {
    }
    
    void Registry::saveKeyRecursive(HKEY hRootKey, std::string currentPath,const Config::ConfigData* currentData, const Config *conf) {
        // ... (Die saveKeyRecursive Logik bleibt unverändert, da sie korrekt den globalen REGISTRY_ROOT_KEY verwendet)
        for (const Config::ConfigData* key = currentData; key != nullptr; key = key->next()) {
            
            std::string localKeyName = key->getKey();
@@ -314,6 +420,66 @@ namespace confplus {
                    subKeyPath += "\\";
                }
                subKeyPath += localKeyName;
                
                // Prüfe ob alle Kinder parallele Arrays sind (sequence-of-mappings).
                // Wenn ja: alle haben Elements > 1 und keine Kinder.
                bool isSeqOfMappings = true;
                size_t maxElements = 0;
                for (const Config::ConfigData* child = key->getChild(); child; child = child->next()) {
                    if (child->childs() || child->getElements() <= 1) {
                        isSeqOfMappings = false;
                        break;
                    }
                    if (child->getElements() > maxElements) {
                        maxElements = child->getElements();
                    }
                }
                
                if (isSeqOfMappings && maxElements > 1) {
                    // Schreibe als numerische Subkeys: PARENT\0\KEY=val, PARENT\1\KEY=val
                    for (size_t idx = 0; idx < maxElements; ++idx) {
                        std::string idxSubKey = subKeyPath + "\\" + std::to_string(idx);
                        HKEY hIdxKey;
                        LONG lRes = RegCreateKeyExA(hRootKey, idxSubKey.c_str(), 0, NULL,
                                                    REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hIdxKey, NULL);
                        if (lRes != ERROR_SUCCESS) {
                            std::cerr << "Failed to create subkey: " << idxSubKey << std::endl;
                            continue;
                        }
                        
                        for (const Config::ConfigData* child = key->getChild(); child; child = child->next()) {
                            if (idx >= child->getElements()) continue;
                            
                            std::string cvalue = conf->getValue(child, idx);
                            std::string childName = child->getKey();
                            
                            if (isInteger(cvalue)) {
                                try {
                                    DWORD dwValue = std::stoul(cvalue);
                                    RegSetValueExA(hIdxKey, childName.c_str(), 0, REG_DWORD,
                                                   (const BYTE*)&dwValue, sizeof(dwValue));
                                } catch (...) {
                                    RegSetValueExA(hIdxKey, childName.c_str(), 0, REG_SZ,
                                                   (const BYTE*)cvalue.c_str(), cvalue.length() + 1);
                                }
                            } else {
                                RegSetValueExA(hIdxKey, childName.c_str(), 0, REG_SZ,
                                               (const BYTE*)cvalue.c_str(), cvalue.length() + 1);
                            }
                        }
                        
                        RegCloseKey(hIdxKey);
                    }
                } else {
                    // Normale Rekursion für Kinder
                    HKEY hSubKey;
                    LONG lRes = RegCreateKeyExA(hRootKey, subKeyPath.c_str(), 0, NULL,
                                                REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hSubKey, NULL);
                    if (lRes == ERROR_SUCCESS) {
                        saveKeyRecursive(hRootKey, subKeyPath, key->getChild(), conf);
                        RegCloseKey(hSubKey);
                    }
                }
            } else {
                if (!subKeyPath.empty()) {
                    subKeyPath += "\\";