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 <application/windoze_helper.h>
16 #include <basis/astring.h>
17 #include <basis/functions.h>
18 #include <basis/utf_conversion.h>
19 #include <structures/static_memory_gremlin.h>
20 #include <structures/string_array.h>
21 #include <structures/string_table.h>
23 using namespace basis;
24 using namespace filesystem;
25 using namespace structures;
29 // this implementation only works on windows currently.
30 //hmmm: i suppose we could fake it with an ini file.
36 #ifdef DEBUG_REGISTRY_CONFIGURATOR
37 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
42 //#define DEBUG_REGISTRY_CONFIGURATOR
43 // uncomment for noisy version.
45 namespace configuration {
47 const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE;
48 // arbitrary maximum for entries we'll read.
50 const int MAXIMUM_NAME_SIZE = 16384;
51 // the longest that value names can be in the registry.
53 // a default we hope never to see in the registry.
54 const astring ®istry_configurator::reg_str_fake_default()
56 static astring _hidden = "bogus_never_should_see";
60 registry_configurator::registry_configurator(registry_hives hive,
61 treatment_of_defaults behavior)
62 : configurator(behavior),
66 registry_configurator::~registry_configurator()
70 // fake the platform dependent names.
71 void *HKEY_CLASSES_ROOT = NULL;
72 void *HKEY_CURRENT_USER = NULL;
73 void *HKEY_LOCAL_MACHINE = NULL;
74 void *HKEY_USERS = NULL;
75 void *HKEY_CURRENT_CONFIG = NULL;
78 void *registry_configurator::translate_hive(registry_hives hive)
81 case hkey_classes_root: return HKEY_CLASSES_ROOT;
82 case hkey_current_user: return HKEY_CURRENT_USER;
83 case hkey_local_machine: return HKEY_LOCAL_MACHINE;
84 case hkey_users: return HKEY_USERS;
85 case hkey_current_config: return HKEY_CURRENT_CONFIG;
90 astring registry_configurator::fix_section(const astring §ion)
92 astring to_return = section;
93 for (int i = 0; i < to_return.length(); i++) {
94 if (to_return[i] == '/')
100 bool registry_configurator::put(const astring §ion_in, const astring &entry,
101 const astring &to_store)
104 astring section = fix_section(section_in);
105 if (!to_store.length()) return delete_entry(section, entry);
106 else if (!section.length()) return false;
110 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
111 to_unicode_temp(section), 0, KEY_WRITE, &key);
112 if (ret != ERROR_SUCCESS) {
113 LOG("failed to open the key, trying to create it.");
114 DWORD dispose; // the disposition of the call (created or existing).
115 ret = RegCreateKeyEx((HKEY)translate_hive(_hive),
116 to_unicode_temp(section), 0, NULL_POINTER, REG_OPTION_NON_VOLATILE,
117 KEY_ALL_ACCESS, NULL_POINTER, &key, &dispose);
118 if (ret != ERROR_SUCCESS) {
119 LOG("failed to create the key!!");
124 bool to_return = true;
125 ret = RegSetValueEx(key, to_unicode_temp(entry), 0, REG_SZ,
126 (byte *)to_store.s(), to_store.length() + 1);
127 if (ret != ERROR_SUCCESS) {
128 LOG(astring("failed to write the entry!"));
139 bool registry_configurator::get(const astring §ion_in, const astring &entry,
144 if (!section_in) return false;
145 if (!entry) {} // not a problem.
146 astring section = fix_section(section_in);
149 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
150 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
151 if (ret != ERROR_SUCCESS) {
152 LOG("failed to open the key!");
157 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
158 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
159 ret = RegQueryValueEx(key, to_unicode_temp(entry), 0, &type_seen, data_seen,
161 if (ret != ERROR_SUCCESS) {
162 LOG(astring("failed to read the entry!"));
166 if (type_seen != REG_SZ) {
167 LOG(astring("entry found was not of string type!"));
172 data_seen[MAXIMUM_ENTRY_SIZE - 1] = '\0';
173 // force last character to be null if data happened to be too big.
174 found = astring((char *)data_seen);
185 bool registry_configurator::get_section(const astring §ion_in,
188 FUNCDEF("get_section");
190 if (!section_in.length()) return false;
191 astring section = fix_section(section_in);
194 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
195 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
196 if (ret != ERROR_SUCCESS) {
197 LOG("failed to open the key!");
202 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
203 flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE];
205 for (DWORD index = 0; true; index++) {
206 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
207 name_length = MAXIMUM_NAME_SIZE - 1;
208 LONG ret = RegEnumValue(key, index, name_seen, &name_length, 0,
209 &type_seen, data_seen, &length);
210 if (ret != ERROR_SUCCESS) break; // no entry at that index.
211 if (type_seen == REG_SZ) {
212 // found an entry successfully and it's the right type.
213 astring name = from_unicode_temp(name_seen);
214 astring content = from_unicode_temp((flexichar *)data_seen);
215 info.add(name, content);
230 bool registry_configurator::section_exists(const astring §ion_in)
232 FUNCDEF("section_exists");
233 if (!section_in.length()) return false;
234 astring section = fix_section(section_in);
237 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
238 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
239 if (ret != ERROR_SUCCESS) {
240 LOG("failed to open the key!");
250 bool registry_configurator::delete_section(const astring §ion_in)
252 FUNCDEF("delete_section");
253 if (!section_in.length()) return false;
254 astring section = fix_section(section_in);
255 //if the key doesn't exist, should that be a failure?
257 long ret = SHDeleteKey((HKEY)translate_hive(_hive),
258 to_unicode_temp(section));
259 if (ret != ERROR_SUCCESS) {
260 LOG("failed to delete the key!");
269 bool registry_configurator::delete_entry(const astring §ion_in,
270 const astring &entry)
272 FUNCDEF("delete_entry");
273 if (!section_in.length()) return false;
274 astring section = fix_section(section_in);
275 if (!entry) {} // no problem.
279 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
280 to_unicode_temp(section), 0, KEY_SET_VALUE, &key);
281 if (ret != ERROR_SUCCESS) {
282 LOG("failed to open the key!");
286 bool to_return = true;
287 ret = RegDeleteValue(key, to_unicode_temp(entry));
288 if (ret != ERROR_SUCCESS) {
289 LOG(astring("failed to delete the entry!"));
300 bool registry_configurator::put_section(const astring §ion_in,
301 const string_table &info)
303 if (!section_in) return false;
304 astring section = fix_section(section_in);
305 bool failures = false;
306 for (int i = 0; i < info.symbols(); i++) {
307 bool worked = put(section, info.name(i), info[i]);
308 if (!worked) failures = true;