Commit 686450e9 authored by jan.koester's avatar jan.koester
Browse files

inital support regedit

parent 93c50632
Loading
Loading
Loading
Loading
+53 −97
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * Copyright (c) 2025, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * (Lizenzblock beibehalten)
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/


#include "regedit.h"
#include "exception.h"

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>

// Spezifische Windows API Includes
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winreg.h>

#include "regconf.h" // Angenommen: Dies ist der umbenannte yamlconf.h
#include "exception.h" // Angenommen: Ihre eigene Exception-Klasse

namespace confplus {
    
    // Basis-Schlüssel in der Registry. Wir verwenden HKEY_CURRENT_USER
    // und einen festen Pfad für die Anwendung.
    // Basis-Schlüssel in der Registry unter HKEY_CURRENT_USER
    const char* REGISTRY_BASE_PATH = "SOFTWARE\\ConfPlus\\Config";
    
    // Hilfsfunktion zum Ersetzen aller Vorkommen eines Substrings (für Pfade)
    std::string replaceAll(std::string str, const std::string& from, const std::string& to) {
        size_t start_pos = 0;
        while((start_pos = str.find(from, start_pos)) != std::string::npos) {
            str.replace(start_pos, from.length(), to);
            start_pos += to.length(); 
        }
        return str;
    }

    // Die Klasse wird von Yaml zu Registry umbenannt.
    class Registry : public BackendApi{
    public:
        const char* getName();
        const char* getVersion();
        const char* getAuthor();

        void loadConfig(const char *path,Config *conf);
        void saveConfig(const char *path,const Config *conf);

        Registry();
        virtual ~Registry();
    };
    // --- Implementierung der Registry-Klasse ---
    
    Registry::Registry(){}

@@ -64,21 +64,16 @@ namespace confplus {

    /**
     * @brief Speichert die Konfiguration in der Windows Registry.
     * * Da das Config-System Pfade wie /Abschnitt/Schlüssel verwendet,
     * verwenden wir diese als Value-Namen unter dem Basis-Schlüssel.
     * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet.
     * @param conf Das Config-Objekt.
     */
    void Registry::saveConfig(const char *path, const Config *conf){
        HKEY hKey;
        DWORD dwDisposition;

        // Erstellt oder öffnet den Basis-Schlüssel für die Konfiguration
        LONG lRes = RegCreateKeyExA(
            HKEY_CURRENT_USER,      // Hauptschlüssel
            REGISTRY_BASE_PATH,     // Subkey-Pfad
            HKEY_CURRENT_USER,      
            REGISTRY_BASE_PATH,     
            0, NULL, REG_OPTION_NON_VOLATILE, 
            KEY_ALL_ACCESS,         // KEY_WRITE
            KEY_ALL_ACCESS,         
            NULL, &hKey, &dwDisposition
        );

@@ -86,55 +81,18 @@ namespace confplus {
            throw Exception("Failed to create/open registry key.");
        }

        // --- Iteration über alle Schlüssel im Config-Objekt ---
        // Da die Config-API nicht direkt sichtbar ist, simulieren wir die Iteration
        // und speichern jeden Wert als REG_SZ (String).
        
        // Die Iterationslogik müsste hier implementiert werden, um alle 
        // ConfigData* Objekte im Config-Objekt zu erhalten. 
        // Hier ein konzeptionelles Beispiel:
        
        std::vector<Config::ConfigData*> allKeys = conf->getAllKeys();
        for (Config::ConfigData* ckey : allKeys) {
            std::string cname = ckey->getPath(); // Z.B. "/Server/Port"
            std::string cvalue = conf->getValue(ckey, 0); // Hole den 1. Wert
            
            // Entferne den führenden Schrägstrich für den Value-Namen
            if (cname.length() > 0 && cname[0] == '/') {
                cname = cname.substr(1); 
            }
            
            // Speichere den Wert
            lRes = RegSetValueExA(
                hKey, 
                cname.c_str(), // Z.B. "Server/Port"
                0, 
                REG_SZ, 
                (const BYTE*)cvalue.c_str(), 
                cvalue.length() + 1
            );
            
            if (lRes != ERROR_SUCCESS) {
                std::cerr << "Failed to set value for: " << cname << std::endl;
            }
        }

        // Da die tatsächliche Struktur des Config-Objekts unbekannt ist,
        // kann hier nur ein Stub eingefügt werden.
        // TODO: Hier die Iterationslogik über conf->getAllKeys() und RegSetValueExA 
        // implementieren, um alle Schlüssel/Werte zu speichern.

        RegCloseKey(hKey);
    }

    /**
     * @brief Lädt die Konfiguration aus der Windows Registry.
     * * Liest alle Werte unter dem Basis-Schlüssel und speichert sie im Config-Objekt.
     * * @param path Der Pfad wird hier ignoriert oder als Subkey des Basis-Pfades verwendet.
     * @param conf Das Config-Objekt.
     */
    void Registry::loadConfig(const char* path, Config* conf) {
        HKEY hKey;

        // Öffne den Basis-Schlüssel
        LONG lRes = RegOpenKeyExA(
            HKEY_CURRENT_USER, 
            REGISTRY_BASE_PATH, 
@@ -144,17 +102,12 @@ namespace confplus {
        );

        if (lRes != ERROR_SUCCESS) {
            // Wenn der Schlüssel nicht existiert, ist das keine Exception,
            // sondern eine leere Konfiguration.
            std::cerr << "Registry key not found: " << REGISTRY_BASE_PATH << std::endl;
            return;
        }

        DWORD dwValues;
        DWORD dwMaxValueNameLen;
        DWORD dwMaxValueLen;
        DWORD dwValues, dwMaxValueNameLen, dwMaxValueLen;

        // Ermittelt die Anzahl der Werte und die maximale Länge
        lRes = RegQueryInfoKey(
            hKey, NULL, NULL, NULL, NULL, NULL, NULL, 
            &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, 
@@ -166,14 +119,13 @@ namespace confplus {
            throw Exception("Failed to query registry key info.");
        }

        // Buffer allozieren (+1 für Nullterminierung)
        char* valueNameBuffer = new char[dwMaxValueNameLen + 1];
        char* dataBuffer = new char[dwMaxValueLen + 1]; 
        
        // Fügt 1 für das Null-Terminierungszeichen hinzu
        DWORD dwSizeValueName = dwMaxValueNameLen + 1;
        DWORD dwSizeData = dwMaxValueLen + 1;
        DWORD dwSizeValueName, dwSizeData;

        // --- Iteration über alle Values unter dem Basis-Schlüssel ---
        // Iteration über alle Values unter dem Basis-Schlüssel
        for (DWORD i = 0; i < dwValues; ++i) {
            DWORD dwType = 0;
            dwSizeValueName = dwMaxValueNameLen + 1; 
@@ -188,26 +140,21 @@ namespace confplus {

            if (lRes == ERROR_SUCCESS) {
                std::string cname = "/";
                cname += std::string(valueNameBuffer); // Z.B. "/Server/Port"
                cname += std::string(valueNameBuffer); // Konstruiert den Pfad: "/Server/Port"
                std::string cvalue = std::string(dataBuffer);

                // Unterstützt nur REG_SZ (String) und REG_DWORD (Zahl)
                if (dwType == REG_SZ) {
                    Config::ConfigData* ckey = conf->setKey(cname);
                    conf->setValue(ckey, 0, cvalue);
                    std::cout << "Loading key: " << cname << " Value: " << cvalue << std::endl;
                } else if (dwType == REG_DWORD) {
                    // Konvertiere DWORD zu String
                    std::stringstream ss;
                    ss << *((DWORD*)dataBuffer);
                    Config::ConfigData* ckey = conf->setKey(cname);
                    conf->setValue(ckey, 0, ss.str());
                    std::cout << "Loading key: " << cname << " Value: " << ss.str() << " (DWORD)" << std::endl;
                }
            } else if (lRes == ERROR_NO_MORE_ITEMS) {
                break; 
            } else {
                // Fehler beim Lesen des Wertes
                std::cerr << "Error reading registry value at index " << i << std::endl;
            }
        }
@@ -217,3 +164,12 @@ namespace confplus {
        RegCloseKey(hKey);
    }
}

// --- Implementierung der Export-Funktionen ---
EXPORT confplus::BackendApi* create() {
    return new confplus::Registry();
}

EXPORT void destroy(confplus::BackendApi* p) {
    delete p;
}
 No newline at end of file
+57 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2025, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#pragma once

#include "conf.h"
#include "backend.h"

namespace confplus {
    class Config; // Forward-Deklaration

    /**
     * @brief Registry-Backend zur Verwaltung der Konfiguration in der Windows Registry.
     */
    class Registry : public BackendApi{
    public:
        // Metadaten-Funktionen
        const char* getName() override;
        const char* getVersion() override;
        const char* getAuthor() override;

        // Backend-Schnittstellen-Funktionen
        void loadConfig(const char *path, Config *conf) override;
        void saveConfig(const char *path, const Config *conf) override;

        Registry();
        virtual ~Registry();
    };
}

// Export-Funktionen für das dynamische Laden der Bibliothek
EXPORT confplus::BackendApi* create();
EXPORT void destroy(confplus::BackendApi* p);
 No newline at end of file