2 * Name : registry_configurator *
3 * Author : Chris Koeritz *
5 * Copyright (c) 2004-$now By Author. This program is free software; you can *
6 * redistribute it and/or modify it under the terms of the GNU General Public *
7 * License as published by the Free Software Foundation; either version 2 of *
8 * the License or (at your option) any later version. This is online at: *
9 * http://www.fsf.org/copyleft/gpl.html *
10 * Please send any updates to: fred@gruntose.com *
13 #include "registry_config.h"
15 #include <basis/astring.h>
16 #include <basis/functions.h>
17 #include <basis/utf_conversion.h>
18 #include <structures/static_memory_gremlin.h>
19 #include <structures/string_array.h>
20 #include <structures/string_table.h>
22 using namespace basis;
23 using namespace filesystem;
24 using namespace structures;
28 // this implementation only works on windows currently.
29 //hmmm: i suppose we could fake it with an ini file.
35 #ifdef DEBUG_REGISTRY_CONFIGURATOR
36 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
41 //#define DEBUG_REGISTRY_CONFIGURATOR
42 // uncomment for noisy version.
44 namespace configuration {
46 const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE;
47 // arbitrary maximum for entries we'll read.
49 const int MAXIMUM_NAME_SIZE = 16384;
50 // the longest that value names can be in the registry.
52 // a default we hope never to see in the registry.
53 //SAFE_STATIC_CONST(astring, registry_configurator::reg_str_fake_default,
54 // ("bogus_never_should_see"));
55 const astring ®istry_configurator::reg_str_fake_default()
57 static astring _hidden = "bogus_never_should_see";
61 registry_configurator::registry_configurator(registry_hives hive,
62 treatment_of_defaults behavior)
63 : configurator(behavior),
67 registry_configurator::~registry_configurator()
71 // fake the platform dependent names.
72 void *HKEY_CLASSES_ROOT = NULL;
73 void *HKEY_CURRENT_USER = NULL;
74 void *HKEY_LOCAL_MACHINE = NULL;
75 void *HKEY_USERS = NULL;
76 void *HKEY_CURRENT_CONFIG = NULL;
79 void *registry_configurator::translate_hive(registry_hives hive)
82 case hkey_classes_root: return HKEY_CLASSES_ROOT;
83 case hkey_current_user: return HKEY_CURRENT_USER;
84 case hkey_local_machine: return HKEY_LOCAL_MACHINE;
85 case hkey_users: return HKEY_USERS;
86 case hkey_current_config: return HKEY_CURRENT_CONFIG;
91 astring registry_configurator::fix_section(const astring §ion)
93 astring to_return = section;
94 for (int i = 0; i < to_return.length(); i++) {
95 if (to_return[i] == '/')
101 bool registry_configurator::put(const astring §ion_in, const astring &entry,
102 const astring &to_store)
105 astring section = fix_section(section_in);
106 if (!to_store.length()) return delete_entry(section, entry);
107 else if (!section.length()) return false;
111 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
112 to_unicode_temp(section), 0, KEY_WRITE, &key);
113 if (ret != ERROR_SUCCESS) {
114 LOG("failed to open the key, trying to create it.");
115 DWORD dispose; // the disposition of the call (created or existing).
116 ret = RegCreateKeyEx((HKEY)translate_hive(_hive),
117 to_unicode_temp(section), 0, NULL_POINTER, REG_OPTION_NON_VOLATILE,
118 KEY_ALL_ACCESS, NULL_POINTER, &key, &dispose);
119 if (ret != ERROR_SUCCESS) {
120 LOG("failed to create the key!!");
125 bool to_return = true;
126 ret = RegSetValueEx(key, to_unicode_temp(entry), 0, REG_SZ,
127 (byte *)to_store.s(), to_store.length() + 1);
128 if (ret != ERROR_SUCCESS) {
129 LOG(astring("failed to write the entry!"));
140 bool registry_configurator::get(const astring §ion_in, const astring &entry,
145 if (!section_in) return false;
146 if (!entry) {} // not a problem.
147 astring section = fix_section(section_in);
150 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
151 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
152 if (ret != ERROR_SUCCESS) {
153 LOG("failed to open the key!");
158 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
159 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
160 ret = RegQueryValueEx(key, to_unicode_temp(entry), 0, &type_seen, data_seen,
162 if (ret != ERROR_SUCCESS) {
163 LOG(astring("failed to read the entry!"));
167 if (type_seen != REG_SZ) {
168 LOG(astring("entry found was not of string type!"));
173 data_seen[MAXIMUM_ENTRY_SIZE - 1] = '\0';
174 // force last character to be null if data happened to be too big.
175 found = astring((char *)data_seen);
186 bool registry_configurator::get_section(const astring §ion_in,
189 FUNCDEF("get_section");
191 if (!section_in.length()) return false;
192 astring section = fix_section(section_in);
195 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
196 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
197 if (ret != ERROR_SUCCESS) {
198 LOG("failed to open the key!");
203 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
204 flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE];
206 for (DWORD index = 0; true; index++) {
207 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
208 name_length = MAXIMUM_NAME_SIZE - 1;
209 LONG ret = RegEnumValue(key, index, name_seen, &name_length, 0,
210 &type_seen, data_seen, &length);
211 if (ret != ERROR_SUCCESS) break; // no entry at that index.
212 if (type_seen == REG_SZ) {
213 // found an entry successfully and it's the right type.
214 astring name = from_unicode_temp(name_seen);
215 astring content = from_unicode_temp((flexichar *)data_seen);
216 info.add(name, content);
231 bool registry_configurator::section_exists(const astring §ion_in)
233 FUNCDEF("section_exists");
234 if (!section_in.length()) return false;
235 astring section = fix_section(section_in);
238 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
239 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
240 if (ret != ERROR_SUCCESS) {
241 LOG("failed to open the key!");
251 bool registry_configurator::delete_section(const astring §ion_in)
253 FUNCDEF("delete_section");
254 if (!section_in.length()) return false;
255 astring section = fix_section(section_in);
256 //if the key doesn't exist, should that be a failure?
258 long ret = SHDeleteKey((HKEY)translate_hive(_hive),
259 to_unicode_temp(section));
260 if (ret != ERROR_SUCCESS) {
261 LOG("failed to delete the key!");
270 bool registry_configurator::delete_entry(const astring §ion_in,
271 const astring &entry)
273 FUNCDEF("delete_entry");
274 if (!section_in.length()) return false;
275 astring section = fix_section(section_in);
276 if (!entry) {} // no problem.
280 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
281 to_unicode_temp(section), 0, KEY_SET_VALUE, &key);
282 if (ret != ERROR_SUCCESS) {
283 LOG("failed to open the key!");
287 bool to_return = true;
288 ret = RegDeleteValue(key, to_unicode_temp(entry));
289 if (ret != ERROR_SUCCESS) {
290 LOG(astring("failed to delete the entry!"));
301 bool registry_configurator::put_section(const astring §ion_in,
302 const string_table &info)
304 if (!section_in) return false;
305 astring section = fix_section(section_in);
306 bool failures = false;
307 for (int i = 0; i < info.symbols(); i++) {
308 bool worked = put(section, info.name(i), info[i]);
309 if (!worked) failures = true;