feisty meow concerns codebase 2.140
registry_config.cpp
Go to the documentation of this file.
1/*
2* Name : registry_configurator *
3* Author : Chris Koeritz *
4**
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 *
11*/
12
13#include "registry_config.h"
14
16#include <basis/astring.h>
17#include <basis/functions.h>
22
23using namespace basis;
24using namespace filesystem;
25using namespace structures;
26
27#ifdef __WIN32__
28
29 // this implementation only works on windows currently.
30//hmmm: i suppose we could fake it with an ini file.
31
32 #include <shlwapi.h>
33#endif
34
35#undef LOG
36#ifdef DEBUG_REGISTRY_CONFIGURATOR
37 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
38#else
39 #define LOG(s) {}
40#endif
41
42//#define DEBUG_REGISTRY_CONFIGURATOR
43 // uncomment for noisy version.
44
45namespace configuration {
46
47const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE;
48 // arbitrary maximum for entries we'll read.
49
50const int MAXIMUM_NAME_SIZE = 16384;
51 // the longest that value names can be in the registry.
52
53// a default we hope never to see in the registry.
54const astring &registry_configurator::reg_str_fake_default()
55{
56 static astring _hidden = "bogus_never_should_see";
57 return _hidden;
58}
59
65
68
69#ifndef __WIN32__
70// fake the platform dependent names.
71void *HKEY_CLASSES_ROOT = NULL;
72void *HKEY_CURRENT_USER = NULL;
73void *HKEY_LOCAL_MACHINE = NULL;
74void *HKEY_USERS = NULL;
76#endif
77
79{
80 switch (hive) {
84 case hkey_users: return HKEY_USERS;
86 default: return 0;
87 }
88}
89
91{
92 astring to_return = section;
93 for (int i = 0; i < to_return.length(); i++) {
94 if (to_return[i] == '/')
95 to_return[i] = '\\';
96 }
97 return to_return;
98}
99
100bool registry_configurator::put(const astring &section_in, const astring &entry,
101 const astring &to_store)
102{
103 FUNCDEF("put");
104 astring section = fix_section(section_in);
105 if (!to_store.length()) return delete_entry(section, entry);
106 else if (!section.length()) return false;
107
108#ifdef __WIN32__
109 HKEY key;
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!!");
120 return false;
121 }
122 }
123
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!"));
129 to_return = false;
130 }
131
132 RegCloseKey(key);
133 return to_return;
134#else
135 return false;
136#endif
137}
138
139bool registry_configurator::get(const astring &section_in, const astring &entry,
140 astring &found)
141{
142 FUNCDEF("get");
143 found = "";
144 if (!section_in) return false;
145 if (!entry) {} // not a problem.
146 astring section = fix_section(section_in);
147#ifdef __WIN32__
148 HKEY key;
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!");
153 return false;
154 }
155
156 DWORD type_seen;
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,
160 &length);
161 if (ret != ERROR_SUCCESS) {
162 LOG(astring("failed to read the entry!"));
163 return false;
164 }
165
166 if (type_seen != REG_SZ) {
167 LOG(astring("entry found was not of string type!"));
168 RegCloseKey(key);
169 return false;
170 }
171
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);
175
176 delete [] data_seen;
177
178 RegCloseKey(key);
179 return true;
180#else
181 return false;
182#endif
183}
184
186 string_table &info)
187{
188 FUNCDEF("get_section");
189 info.reset();
190 if (!section_in.length()) return false;
191 astring section = fix_section(section_in);
192#ifdef __WIN32__
193 HKEY key;
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!");
198 return false;
199 }
200
201 DWORD type_seen;
202 byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
203 flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE];
204 DWORD name_length;
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);
216 }
217 }
218
219 delete [] data_seen;
220 delete [] name_seen;
221
222 RegCloseKey(key);
223
224 return true;
225#else
226 return false;
227#endif
228}
229
231{
232 FUNCDEF("section_exists");
233 if (!section_in.length()) return false;
234 astring section = fix_section(section_in);
235#ifdef __WIN32__
236 HKEY key;
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!");
241 return false;
242 }
243 RegCloseKey(key);
244 return true;
245#else
246 return false;
247#endif
248}
249
251{
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?
256#ifdef __WIN32__
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!");
261 return false;
262 }
263 return true;
264#else
265 return false;
266#endif
267}
268
270 const astring &entry)
271{
272 FUNCDEF("delete_entry");
273 if (!section_in.length()) return false;
274 astring section = fix_section(section_in);
275 if (!entry) {} // no problem.
276
277#ifdef __WIN32__
278 HKEY key;
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!");
283 return false;
284 }
285
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!"));
290 to_return = false;
291 }
292
293 RegCloseKey(key);
294 return to_return;
295#else
296 return false;
297#endif
298}
299
301 const string_table &info)
302{
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;
309 }
310 return !failures;
311}
312
313} // namespace
314
#define LOG(s)
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition astring.h:113
int length() const
Returns the current length of the string.
Definition astring.cpp:132
Provides a base class for configuration repositories.
registry_configurator(registry_hives hive, treatment_of_defaults behavior)
creates a registry_configurator that stores entries into the "hive".
virtual bool put_section(const basis::astring &section, const structures::string_table &info)
writes a table called "info" into the "section" in the INI file.
basis::astring fix_section(const basis::astring &section)
repairs malformed section names.
virtual bool put(const basis::astring &section, const basis::astring &entry, const basis::astring &to_store)
implements the configurator storage function.
virtual bool section_exists(const basis::astring &section)
returns true if the "section" was found in the file.
void * translate_hive(registry_hives hive)
translates from our enum to the windows specific type for hives.
virtual bool get_section(const basis::astring &section, structures::string_table &info)
reads the entire "section" into a table called "info".
virtual bool delete_entry(const basis::astring &section, const basis::astring &entry)
removes the entry specified by the "section" and "entry" name.
registry_hives
the hives are major partitions of the registry.
virtual bool delete_section(const basis::astring &section)
removes the entire "section" specified.
virtual bool get(const basis::astring &section, const basis::astring &entry, basis::astring &found)
implements the configurator retrieval function.
Provides a symbol_table that holds strings as the content.
const basis::astring & name(int index) const
returns the name held at the "index".
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
int symbols() const
returns the number of symbols listed in the table.
#define NULL_POINTER
The value representing a pointer to nothing.
Definition definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
char flexichar
Definition definitions.h:58
const int KILOBYTE
Number of bytes in a kilobyte.
const int MAXIMUM_NAME_SIZE
const int MAXIMUM_ENTRY_SIZE
A platform independent way to obtain the timestamp of a file.
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55
Support for unicode builds.
Aids in achievement of platform independence.
unsigned long DWORD