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>
18 #include <basis/utf_conversion.h>
22 
23 using namespace basis;
24 using namespace filesystem;
25 using 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 
45 namespace configuration {
46 
47 const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE;
48  // arbitrary maximum for entries we'll read.
49 
50 const 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.
54 const astring &registry_configurator::reg_str_fake_default()
55 {
56  static astring _hidden = "bogus_never_should_see";
57  return _hidden;
58 }
59 
60 registry_configurator::registry_configurator(registry_hives hive,
61  treatment_of_defaults behavior)
62 : configurator(behavior),
63  _hive(hive)
64 {}
65 
67 {}
68 
69 #ifndef __WIN32__
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;
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 
100 bool 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 
139 bool 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 
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.
Definition: configurator.h:34
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.
Definition: string_table.h:32
const basis::astring & name(int index) const
returns the name held at the "index".
Definition: symbol_table.h:272
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
Definition: symbol_table.h:383
int symbols() const
returns the number of symbols listed in the table.
Definition: symbol_table.h:241
#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:57
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.
Definition: definitions.h:134
void * HKEY_CURRENT_USER
void * HKEY_LOCAL_MACHINE
void * HKEY_CLASSES_ROOT
void * HKEY_CURRENT_CONFIG
const int MAXIMUM_NAME_SIZE
const int MAXIMUM_ENTRY_SIZE
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#define LOG(s)
Support for unicode builds.
Aids in achievement of platform independence.
unsigned long DWORD