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

inital support regedit

parent f96322d6
Loading
Loading
Loading
Loading
+121 −39
Original line number Diff line number Diff line
@@ -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();
@@ -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,
@@ -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)) {
@@ -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,
@@ -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);
            }
@@ -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") {
@@ -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() {