registry_config.cpp

Go to the documentation of this file.
00001 #ifndef REGISTRY_CONFIG_IMPLEMENTATION_FILE
00002 #define REGISTRY_CONFIG_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : registry_configurator                                             *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 2004-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #ifdef __WIN32__
00019   // this implementation only works on windows currently.
00020 //hmmm: i suppose we could fake it with an ini file.
00021 
00022 #include "registry_config.h"
00023 
00024 #include <basis/convert_utf.h>
00025 #include <basis/function.h>
00026 #include <basis/istring.h>
00027 #include <basis/portable.h>
00028 #include <basis/string_array.h>
00029 #include <data_struct/static_memory_gremlin.h>
00030 #include <data_struct/string_table.h>
00031 
00032 #include <shlwapi.h>
00033 
00034 #undef LOG
00035 #ifdef DEBUG_REGISTRY_CONFIGURATOR
00036   #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00037 #else
00038   #define LOG(s) {}
00039 #endif
00040 
00041 //#define DEBUG_REGISTRY_CONFIGURATOR
00042   // uncomment for noisy version.
00043 
00044 const int MAXIMUM_ENTRY_SIZE = 256 * KILOBYTE;
00045   // arbitrary maximum for entries we'll read.
00046 
00047 const int MAXIMUM_NAME_SIZE = 16384;
00048   // the longest that value names can be in the registry.
00049 
00050 // a default we hope never to see in the registry.
00051 SAFE_STATIC_CONST(istring_object, registry_configurator::reg_str_fake_default,
00052     ("bogus_never_should_see"));
00053 
00054 registry_configurator::registry_configurator(registry_hives hive,
00055       treatment_of_defaults behavior)
00056 : configurator(behavior),
00057   _hive(hive)
00058 {}
00059 
00060 registry_configurator::~registry_configurator()
00061 {}
00062 
00063 void *registry_configurator::translate_hive(registry_hives hive)
00064 {
00065   switch (hive) {
00066     case hkey_classes_root: return HKEY_CLASSES_ROOT;
00067     case hkey_current_user: return HKEY_CURRENT_USER;
00068     case hkey_local_machine: return HKEY_LOCAL_MACHINE;
00069     case hkey_users: return HKEY_USERS;
00070     case hkey_current_config: return HKEY_CURRENT_CONFIG;
00071     default: return 0;
00072   }
00073 }
00074 
00075 istring registry_configurator::fix_section(const istring &section)
00076 {
00077   istring to_return = section;
00078   for (int i = 0; i < to_return.length(); i++) {
00079     if (to_return[i] == '/')
00080       to_return[i] = '\\';
00081   }
00082   return to_return;
00083 }
00084 
00085 bool registry_configurator::put(const istring &section_in, const istring &entry,
00086     const istring &to_store)
00087 {
00088   FUNCDEF("put");
00089   istring section = fix_section(section_in);
00090   if (!to_store.length()) return delete_entry(section, entry);
00091   else if (!section.length()) return false;
00092 
00093   HKEY key;
00094   long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
00095       to_unicode_temp(section), 0, KEY_WRITE, &key);
00096   if (ret != ERROR_SUCCESS) {
00097     LOG("failed to open the key, trying to create it.");
00098     DWORD dispose;  // the disposition of the call (created or existing).
00099     ret = RegCreateKeyEx((HKEY)translate_hive(_hive),
00100         to_unicode_temp(section), 0, NIL, REG_OPTION_NON_VOLATILE,
00101         KEY_ALL_ACCESS, NIL, &key, &dispose);
00102     if (ret != ERROR_SUCCESS) {
00103       LOG("failed to create the key!!");
00104       return false;
00105     }
00106   }
00107 
00108   bool to_return = true;
00109   ret = RegSetValueEx(key, to_unicode_temp(entry), 0, REG_SZ,
00110       (byte *)to_store.s(), to_store.length() + 1);
00111   if (ret != ERROR_SUCCESS) {
00112     LOG(istring("failed to write the entry!"));
00113     to_return = false;
00114   }
00115 
00116   RegCloseKey(key);
00117   return to_return;
00118 }
00119 
00120 bool registry_configurator::get(const istring &section_in, const istring &entry,
00121     istring &found)
00122 {
00123   FUNCDEF("get");
00124   found = "";
00125   if (!section_in) return false;
00126   istring section = fix_section(section_in);
00127   HKEY key;
00128   long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
00129       to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
00130   if (ret != ERROR_SUCCESS) {
00131     LOG("failed to open the key!");
00132     return false;
00133   }
00134 
00135   DWORD type_seen;
00136   byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
00137   DWORD length = MAXIMUM_ENTRY_SIZE - 1;
00138   ret = RegQueryValueEx(key, to_unicode_temp(entry), 0, &type_seen, data_seen,
00139       &length);
00140   if (ret != ERROR_SUCCESS) {
00141     LOG(istring("failed to read the entry!"));
00142     return false;
00143   }
00144 
00145   if (type_seen != REG_SZ) {
00146     LOG(istring("entry found was not of string type!"));
00147     RegCloseKey(key);
00148     return false;
00149   }
00150 
00151   data_seen[MAXIMUM_ENTRY_SIZE - 1] = '\0';
00152     // force last character to be null if data happened to be too big.
00153   found = istring((char *)data_seen);
00154 
00155   delete [] data_seen;
00156 
00157   RegCloseKey(key);
00158   return true;
00159 }
00160 
00161 bool registry_configurator::get_section(const istring &section_in,
00162     string_table &info)
00163 {
00164   FUNCDEF("get_section");
00165   info.reset();
00166   if (!section_in.length()) return false;
00167   istring section = fix_section(section_in);
00168   HKEY key;
00169   long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
00170       to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
00171   if (ret != ERROR_SUCCESS) {
00172     LOG("failed to open the key!");
00173     return false;
00174   }
00175 
00176   DWORD type_seen;
00177   byte *data_seen = new byte[MAXIMUM_ENTRY_SIZE];
00178   flexichar *name_seen = new flexichar[MAXIMUM_NAME_SIZE];
00179   DWORD name_length;
00180   for (DWORD index = 0; index++; ) {
00181     DWORD length = MAXIMUM_ENTRY_SIZE - 1;
00182     LONG ret = RegEnumValue(key, index, name_seen, &name_length, 0,
00183         &type_seen, data_seen, &length);
00184     if ( (ret == ERROR_SUCCESS) && (type_seen == REG_SZ) ) {
00185       // found an entry successfully and it's the right type.
00186       istring name = from_unicode_temp(name_seen);
00187       istring content = from_unicode_temp((flexichar *)data_seen);
00188       info.add(name, content);
00189     }
00190   }
00191 
00192   delete [] data_seen;
00193   delete [] name_seen;
00194 
00195   RegCloseKey(key);
00196 
00197   return true;
00198 }
00199 
00200 bool registry_configurator::section_exists(const istring &section_in)
00201 {
00202   FUNCDEF("section_exists");
00203   if (!section_in.length()) return false;
00204   istring section = fix_section(section_in);
00205   HKEY key;
00206   long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
00207       to_unicode_temp(section), 0, KEY_QUERY_VALUE, &key);
00208   if (ret != ERROR_SUCCESS) {
00209     LOG("failed to open the key!");
00210     return false;
00211   }
00212 
00213   RegCloseKey(key);
00214 
00215   return true;
00216 }
00217 
00218 bool registry_configurator::delete_section(const istring &section_in)
00219 {
00220   FUNCDEF("delete_section");
00221   if (!section_in.length()) return false;
00222   istring section = fix_section(section_in);
00223 //if the key doesn't exist, should that be a failure?
00224   long ret = SHDeleteKey((HKEY)translate_hive(_hive),
00225       to_unicode_temp(section));
00226   if (ret != ERROR_SUCCESS) {
00227     LOG("failed to delete the key!");
00228     return false;
00229   }
00230   return true;
00231 }
00232 
00233 bool registry_configurator::delete_entry(const istring &section_in,
00234     const istring &entry)
00235 {
00236   FUNCDEF("delete_entry");
00237   if (!section_in.length()) return false;
00238   istring section = fix_section(section_in);
00239 
00240   HKEY key;
00241   long ret = RegOpenKeyEx((HKEY)translate_hive(_hive),
00242       to_unicode_temp(section), 0, KEY_SET_VALUE, &key);
00243   if (ret != ERROR_SUCCESS) {
00244     LOG("failed to open the key!");
00245     return false;
00246   }
00247 
00248   bool to_return = true;
00249   ret = RegDeleteValue(key, to_unicode_temp(entry));
00250   if (ret != ERROR_SUCCESS) {
00251     LOG(istring("failed to delete the entry!"));
00252     to_return = false;
00253   }
00254 
00255   RegCloseKey(key);
00256   return to_return;
00257 }
00258 
00259 bool registry_configurator::put_section(const istring &section_in,
00260     const string_table &info)
00261 {
00262   if (!section_in) return false;
00263   istring section = fix_section(section_in);
00264   bool failures = false;
00265   for (int i = 0; i < info.symbols(); i++) {
00266     bool worked = put(section, info.name(i), info[i]);
00267     if (!worked) failures = true;
00268   }
00269   return !failures;
00270 }
00271 
00272 #endif // __WIN32__
00273 
00274 
00275 #endif //REGISTRY_CONFIG_IMPLEMENTATION_FILE
00276 

Generated on Fri Nov 28 04:29:30 2008 for HOOPLE Libraries by  doxygen 1.5.1