From cfd4b817219daac2fec679b67119112d5efe9b92 Mon Sep 17 00:00:00 2001 From: Chris Koeritz Date: Sun, 15 Apr 2012 16:20:22 -0400 Subject: [PATCH] new file from hooples. --- nucleus/library/application/makefile | 4 +- .../library/application/registry_config.cpp | 315 ++++++++++++++++++ nucleus/library/application/registry_config.h | 102 ++++++ 3 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 nucleus/library/application/registry_config.cpp create mode 100644 nucleus/library/application/registry_config.h diff --git a/nucleus/library/application/makefile b/nucleus/library/application/makefile index 758240c5..c2548b55 100644 --- a/nucleus/library/application/makefile +++ b/nucleus/library/application/makefile @@ -3,8 +3,8 @@ include cpp/variables.def PROJECT = application TYPE = library SOURCE = application_shell.cpp callstack_tracker.cpp command_line.cpp dll_root.cpp \ - hoople_service.cpp launch_manager.cpp memory_checker.cpp redirecter.cpp shared_memory.cpp \ - singleton_application.cpp windoze_helper.cpp + hoople_service.cpp launch_manager.cpp memory_checker.cpp redirecter.cpp \ + registry_config.cpp shared_memory.cpp singleton_application.cpp windoze_helper.cpp TARGETS = application.lib LOCAL_LIBS_USED = basis diff --git a/nucleus/library/application/registry_config.cpp b/nucleus/library/application/registry_config.cpp new file mode 100644 index 00000000..96f9fc92 --- /dev/null +++ b/nucleus/library/application/registry_config.cpp @@ -0,0 +1,315 @@ +/* +* Name : registry_configurator * +* Author : Chris Koeritz * +** +* Copyright (c) 2004-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +*/ + +#include "registry_config.h" + +#include +#include +#include +#include +#include +#include + +using namespace basis; +using namespace filesystem; +using namespace structures; + +#ifdef __WIN32__ + + // this implementation only works on windows currently. +//hmmm: i suppose we could fake it with an ini file. + + #include +#endif + +#undef LOG +#ifdef DEBUG_REGISTRY_CONFIGURATOR + #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s) +#else + #define LOG(s) {} +#endif + +//#define DEBUG_REGISTRY_CONFIGURATOR + // uncomment for noisy version. + +namespace configuration { + +const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE; + // arbitrary maximum for entries we'll read. + +const int MAXIMUM_NAME_SIZE = 16384; + // the longest that value names can be in the registry. + +// a default we hope never to see in the registry. +//SAFE_STATIC_CONST(astring, registry_configurator::reg_str_fake_default, + // ("bogus_never_should_see")); +const astring ®istry_configurator::reg_str_fake_default() +{ + static astring _hidden = "bogus_never_should_see"; + return _hidden; +} + +registry_configurator::registry_configurator(registry_hives hive, + treatment_of_defaults behavior) +: configurator(behavior), + _hive(hive) +{} + +registry_configurator::~registry_configurator() +{} + +#ifndef __WIN32__ +// fake the platform dependent names. +void *HKEY_CLASSES_ROOT = NULL; +void *HKEY_CURRENT_USER = NULL; +void *HKEY_LOCAL_MACHINE = NULL; +void *HKEY_USERS = NULL; +void *HKEY_CURRENT_CONFIG = NULL; +#endif + +void *registry_configurator::translate_hive(registry_hives hive) +{ + switch (hive) { + case hkey_classes_root: return HKEY_CLASSES_ROOT; + case hkey_current_user: return HKEY_CURRENT_USER; + case hkey_local_machine: return HKEY_LOCAL_MACHINE; + case hkey_users: return HKEY_USERS; + case hkey_current_config: return HKEY_CURRENT_CONFIG; + default: return 0; + } +} + +astring registry_configurator::fix_section(const astring §ion) +{ + astring to_return = section; + for (int i = 0; i < to_return.length(); i++) { + if (to_return[i] == '/') + to_return[i] = '\\'; + } + return to_return; +} + +bool registry_configurator::put(const astring §ion_in, const astring &entry, + const astring &to_store) +{ + FUNCDEF("put"); + astring section = fix_section(section_in); + if (!to_store.length()) return delete_entry(section, entry); + else if (!section.length()) return false; + +#ifdef __WIN32__ + HKEY key; + long ret = RegOpenKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, KEY_WRITE, &key); + if (ret != ERROR_SUCCESS) { + LOG("failed to open the key, trying to create it."); + DWORD dispose; // the disposition of the call (created or existing). + ret = RegCreateKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, NIL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, NIL, &key, &dispose); + if (ret != ERROR_SUCCESS) { + LOG("failed to create the key!!"); + return false; + } + } + + bool to_return = true; + ret = RegSetValueEx(key, to_unicode_temp(entry), 0, REG_SZ, + (byte *)to_store.s(), to_store.length() + 1); + if (ret != ERROR_SUCCESS) { + LOG(astring("failed to write the entry!")); + to_return = false; + } + + RegCloseKey(key); + return to_return; +#else + return false; +#endif +} + +bool registry_configurator::get(const astring §ion_in, const astring &entry, + astring &found) +{ + FUNCDEF("get"); + found = ""; + if (!section_in) return false; + if (!entry) {} // not a problem. + astring section = fix_section(section_in); +#ifdef __WIN32__ + HKEY key; + long ret = RegOpenKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key); + if (ret != ERROR_SUCCESS) { + LOG("failed to open the key!"); + return false; + } + + DWORD type_seen; + byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE]; + DWORD length = MAXIMUM_ENTRY_SIZE - 1; + ret = RegQueryValueEx(key, to_unicode_temp(entry), 0, &type_seen, data_seen, + &length); + if (ret != ERROR_SUCCESS) { + LOG(astring("failed to read the entry!")); + return false; + } + + if (type_seen != REG_SZ) { + LOG(astring("entry found was not of string type!")); + RegCloseKey(key); + return false; + } + + data_seen[MAXIMUM_ENTRY_SIZE - 1] = '\0'; + // force last character to be null if data happened to be too big. + found = astring((char *)data_seen); + + delete [] data_seen; + + RegCloseKey(key); + return true; +#else + return false; +#endif +} + +bool registry_configurator::get_section(const astring §ion_in, + string_table &info) +{ + FUNCDEF("get_section"); + info.reset(); + if (!section_in.length()) return false; + astring section = fix_section(section_in); +#ifdef __WIN32__ + HKEY key; + long ret = RegOpenKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key); + if (ret != ERROR_SUCCESS) { + LOG("failed to open the key!"); + return false; + } + + DWORD type_seen; + byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE]; + flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE]; + DWORD name_length; + for (DWORD index = 0; true; index++) { + DWORD length = MAXIMUM_ENTRY_SIZE - 1; + name_length = MAXIMUM_NAME_SIZE - 1; + LONG ret = RegEnumValue(key, index, name_seen, &name_length, 0, + &type_seen, data_seen, &length); + if (ret != ERROR_SUCCESS) break; // no entry at that index. + if (type_seen == REG_SZ) { + // found an entry successfully and it's the right type. + astring name = from_unicode_temp(name_seen); + astring content = from_unicode_temp((flexichar *)data_seen); + info.add(name, content); + } + } + + delete [] data_seen; + delete [] name_seen; + + RegCloseKey(key); + + return true; +#else + return false; +#endif +} + +bool registry_configurator::section_exists(const astring §ion_in) +{ + FUNCDEF("section_exists"); + if (!section_in.length()) return false; + astring section = fix_section(section_in); +#ifdef __WIN32__ + HKEY key; + long ret = RegOpenKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key); + if (ret != ERROR_SUCCESS) { + LOG("failed to open the key!"); + return false; + } + RegCloseKey(key); + return true; +#else + return false; +#endif +} + +bool registry_configurator::delete_section(const astring §ion_in) +{ + FUNCDEF("delete_section"); + if (!section_in.length()) return false; + astring section = fix_section(section_in); +//if the key doesn't exist, should that be a failure? +#ifdef __WIN32__ + long ret = SHDeleteKey((HKEY)translate_hive(_hive), + to_unicode_temp(section)); + if (ret != ERROR_SUCCESS) { + LOG("failed to delete the key!"); + return false; + } + return true; +#else + return false; +#endif +} + +bool registry_configurator::delete_entry(const astring §ion_in, + const astring &entry) +{ + FUNCDEF("delete_entry"); + if (!section_in.length()) return false; + astring section = fix_section(section_in); + if (!entry) {} // no problem. + +#ifdef __WIN32__ + HKEY key; + long ret = RegOpenKeyEx((HKEY)translate_hive(_hive), + to_unicode_temp(section), 0, KEY_SET_VALUE, &key); + if (ret != ERROR_SUCCESS) { + LOG("failed to open the key!"); + return false; + } + + bool to_return = true; + ret = RegDeleteValue(key, to_unicode_temp(entry)); + if (ret != ERROR_SUCCESS) { + LOG(astring("failed to delete the entry!")); + to_return = false; + } + + RegCloseKey(key); + return to_return; +#else + return false; +#endif +} + +bool registry_configurator::put_section(const astring §ion_in, + const string_table &info) +{ + if (!section_in) return false; + astring section = fix_section(section_in); + bool failures = false; + for (int i = 0; i < info.symbols(); i++) { + bool worked = put(section, info.name(i), info[i]); + if (!worked) failures = true; + } + return !failures; +} + +} // namespace + diff --git a/nucleus/library/application/registry_config.h b/nucleus/library/application/registry_config.h new file mode 100644 index 00000000..f68cc866 --- /dev/null +++ b/nucleus/library/application/registry_config.h @@ -0,0 +1,102 @@ +#ifndef REGISTRY_CONFIGURATOR_CLASS +#define REGISTRY_CONFIGURATOR_CLASS + +/* +* Name : registry_configurator * +* Author : Chris Koeritz * +** +* Copyright (c) 2004-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +*/ + +#include +#include +#include +#include + +namespace configuration { + +//! Supports the configurator class interface on the windows registry. + +class registry_configurator : public configurator +{ +public: + //! the hives are major partitions of the registry. + enum registry_hives { + hkey_classes_root, + hkey_current_user, + hkey_local_machine, + hkey_users, + hkey_current_config, + // abbreviations for the above sections... + HKCR = hkey_classes_root, + HKCU = hkey_current_user, + HKLM = hkey_local_machine, + HKU = hkey_users, + HKCC = hkey_current_config + }; + + registry_configurator(registry_hives hive, treatment_of_defaults behavior); + //!< creates a registry_configurator that stores entries into the "hive". + /*!< applies the "behavior" to items that are not found. */ + + virtual ~registry_configurator(); + + DEFINE_CLASS_NAME("registry_configurator"); + + virtual bool get(const basis::astring §ion, const basis::astring &entry, + basis::astring &found); + //!< implements the configurator retrieval function. + /*!< note that for registry based retrieval, an empty "entry" is allowed, + and that specifies the default item in the "section". */ + + virtual bool section_exists(const basis::astring §ion); + //!< returns true if the "section" was found in the file. + + virtual bool put(const basis::astring §ion, const basis::astring &entry, + const basis::astring &to_store); + //!< implements the configurator storage function. + /*!< put interprets an empty string for "entry" as pointing at the + default item in the "section". */ + + virtual bool delete_section(const basis::astring §ion); + //!< removes the entire "section" specified. + + virtual bool delete_entry(const basis::astring §ion, const basis::astring &entry); + //!< removes the entry specified by the "section" and "entry" name. + + virtual bool get_section(const basis::astring §ion, structures::string_table &info); + //!< reads the entire "section" into a table called "info". + /*!< on win-9x, this will fail if the section's data exceeds 32K. */ + + virtual bool put_section(const basis::astring §ion, const structures::string_table &info); + //!< writes a table called "info" into the "section" in the INI file. + /*!< any existing data for that section is wiped out. on win-9x, this will + fail if the section's data exceeds 32K. */ + + void *translate_hive(registry_hives hive); + //!< translates from our enum to the windows specific type for hives. + + basis::astring fix_section(const basis::astring §ion); + //!< repairs malformed section names. + /*!< translates a section name that might use forward slashes into the + form required for windows that uses backslashes. */ + +private: + registry_hives _hive; //!< which hive our entries are stored in. + + // not to be called. + registry_configurator(const registry_configurator &); + registry_configurator &operator =(const registry_configurator &); + + static const basis::astring ®_str_fake_default(); +}; + +} + +#endif + -- 2.34.1