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 //SAFE_STATIC_CONST(astring, registry_configurator::reg_str_fake_default,
55 // ("bogus_never_should_see"));
56 const astring ®istry_configurator::reg_str_fake_default()
58 static astring _hidden = "bogus_never_should_see";
62 registry_configurator::registry_configurator(registry_hives hive,
63 treatment_of_defaults behavior)
64 : configurator(behavior),
68 registry_configurator::~registry_configurator()
72 // fake the platform dependent names.
73 void *HKEY_CLASSES_ROOT = NULL;
74 void *HKEY_CURRENT_USER = NULL;
75 void *HKEY_LOCAL_MACHINE = NULL;
76 void *HKEY_USERS = NULL;
77 void *HKEY_CURRENT_CONFIG = NULL;
80 void *registry_configurator::translate_hive(registry_hives hive)
83 case hkey_classes_root: return HKEY_CLASSES_ROOT;
84 case hkey_current_user: return HKEY_CURRENT_USER;
85 case hkey_local_machine: return HKEY_LOCAL_MACHINE;
86 case hkey_users: return HKEY_USERS;
87 case hkey_current_config: return HKEY_CURRENT_CONFIG;
92 astring registry_configurator::fix_section(const astring §ion)
94 astring to_return = section;
95 for (int i = 0; i < to_return.length(); i++) {
96 if (to_return[i] == '/')
102 bool registry_configurator::put(const astring §ion_in, const astring &entry,
103 const astring &to_store)
106 astring section = fix_section(section_in);
107 if (!to_store.length()) return delete_entry(section, entry);
108 else if (!section.length()) return false;
112 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
113 to_unicode_temp(section), 0, KEY_WRITE, &key);
114 if (ret != ERROR_SUCCESS) {
115 LOG("failed to open the key, trying to create it.");
116 DWORD dispose; // the disposition of the call (created or existing).
117 ret = RegCreateKeyEx((HKEY)translate_hive(_hive),
118 to_unicode_temp(section), 0, NULL_POINTER, REG_OPTION_NON_VOLATILE,
119 KEY_ALL_ACCESS, NULL_POINTER, &key, &dispose);
120 if (ret != ERROR_SUCCESS) {
121 LOG("failed to create the key!!");
126 bool to_return = true;
127 ret = RegSetValueEx(key, to_unicode_temp(entry), 0, REG_SZ,
128 (byte *)to_store.s(), to_store.length() + 1);
129 if (ret != ERROR_SUCCESS) {
130 LOG(astring("failed to write the entry!"));
141 bool registry_configurator::get(const astring §ion_in, const astring &entry,
146 if (!section_in) return false;
147 if (!entry) {} // not a problem.
148 astring section = fix_section(section_in);
151 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
152 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
153 if (ret != ERROR_SUCCESS) {
154 LOG("failed to open the key!");
159 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
160 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
161 ret = RegQueryValueEx(key, to_unicode_temp(entry), 0, &type_seen, data_seen,
163 if (ret != ERROR_SUCCESS) {
164 LOG(astring("failed to read the entry!"));
168 if (type_seen != REG_SZ) {
169 LOG(astring("entry found was not of string type!"));
174 data_seen[MAXIMUM_ENTRY_SIZE - 1] = '\0';
175 // force last character to be null if data happened to be too big.
176 found = astring((char *)data_seen);
187 bool registry_configurator::get_section(const astring §ion_in,
190 FUNCDEF("get_section");
192 if (!section_in.length()) return false;
193 astring section = fix_section(section_in);
196 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
197 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
198 if (ret != ERROR_SUCCESS) {
199 LOG("failed to open the key!");
204 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
205 flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE];
207 for (DWORD index = 0; true; index++) {
208 DWORD length = MAXIMUM_ENTRY_SIZE - 1;
209 name_length = MAXIMUM_NAME_SIZE - 1;
210 LONG ret = RegEnumValue(key, index, name_seen, &name_length, 0,
211 &type_seen, data_seen, &length);
212 if (ret != ERROR_SUCCESS) break; // no entry at that index.
213 if (type_seen == REG_SZ) {
214 // found an entry successfully and it's the right type.
215 astring name = from_unicode_temp(name_seen);
216 astring content = from_unicode_temp((flexichar *)data_seen);
217 info.add(name, content);
232 bool registry_configurator::section_exists(const astring §ion_in)
234 FUNCDEF("section_exists");
235 if (!section_in.length()) return false;
236 astring section = fix_section(section_in);
239 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
240 to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
241 if (ret != ERROR_SUCCESS) {
242 LOG("failed to open the key!");
252 bool registry_configurator::delete_section(const astring §ion_in)
254 FUNCDEF("delete_section");
255 if (!section_in.length()) return false;
256 astring section = fix_section(section_in);
257 //if the key doesn't exist, should that be a failure?
259 long ret = SHDeleteKey((HKEY)translate_hive(_hive),
260 to_unicode_temp(section));
261 if (ret != ERROR_SUCCESS) {
262 LOG("failed to delete the key!");
271 bool registry_configurator::delete_entry(const astring §ion_in,
272 const astring &entry)
274 FUNCDEF("delete_entry");
275 if (!section_in.length()) return false;
276 astring section = fix_section(section_in);
277 if (!entry) {} // no problem.
281 long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
282 to_unicode_temp(section), 0, KEY_SET_VALUE, &key);
283 if (ret != ERROR_SUCCESS) {
284 LOG("failed to open the key!");
288 bool to_return = true;
289 ret = RegDeleteValue(key, to_unicode_temp(entry));
290 if (ret != ERROR_SUCCESS) {
291 LOG(astring("failed to delete the entry!"));
302 bool registry_configurator::put_section(const astring §ion_in,
303 const string_table &info)
305 if (!section_in) return false;
306 astring section = fix_section(section_in);
307 bool failures = false;
308 for (int i = 0; i < info.symbols(); i++) {
309 bool worked = put(section, info.name(i), info[i]);
310 if (!worked) failures = true;