00001
00002
00003
00004
00005
00006
00007 #include "uniregistrygen.h"
00008 #include "wvmoniker.h"
00009 #include "wvlinkerhack.h"
00010
00011 WV_LINK(UniRegistryGen);
00012
00013
00014
00015
00016 static HKEY follow_path(HKEY from, const UniConfKey &key,
00017 bool create, bool *isValue)
00018 {
00019 const REGSAM samDesired = KEY_READ | KEY_WRITE;
00020 LONG result;
00021 HKEY hLastKey = from;
00022 int n = key.numsegments();
00023
00024 if (isValue) *isValue = false;
00025
00026 for (int i=0;i<n;i++)
00027 {
00028 WvString subkey = key.segment(i).printable();
00029 HKEY hNextKey;
00030
00031 if (create)
00032 {
00033 result = RegCreateKeyEx(hLastKey, subkey, 0, NULL, 0, samDesired,
00034 NULL, &hNextKey, NULL);
00035 }
00036 else
00037 {
00038 result = RegOpenKeyEx(hLastKey, subkey, 0, samDesired, &hNextKey);
00039 }
00040
00041 if ((result == ERROR_FILE_NOT_FOUND) && (i == n-1))
00042 {
00043 WvString xsub(subkey=="." ? WvString::null : subkey);
00044
00045
00046 if (RegQueryValueEx(hLastKey, xsub, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
00047 {
00048
00049 if (isValue) *isValue = true;
00050 break;
00051 }
00052 }
00053 if (result != ERROR_SUCCESS)
00054 {
00055 return 0;
00056 }
00057
00058
00059 if (i > 0)
00060 {
00061 RegCloseKey(hLastKey);
00062 }
00063 hLastKey = hNextKey;
00064 }
00065
00066 return hLastKey;
00067 }
00068
00069
00070 UniRegistryGen::UniRegistryGen(WvString _moniker) :
00071 m_log(_moniker), m_hRoot(0)
00072 {
00073 UniConfKey key = _moniker;
00074 WvString hive = key.first().printable();
00075 if (strcmp("HKEY_CLASSES_ROOT", hive) == 0)
00076 {
00077 m_hRoot = HKEY_CLASSES_ROOT;
00078 }
00079 else if (strcmp("HKEY_CURRENT_USER", hive) == 0)
00080 {
00081 m_hRoot = HKEY_CURRENT_USER;
00082 }
00083 else if (strcmp("HKEY_LOCAL_MACHINE", hive) == 0)
00084 {
00085 m_hRoot = HKEY_LOCAL_MACHINE;
00086 }
00087 else if (strcmp("HKEY_USERS", hive) == 0)
00088 {
00089 m_hRoot = HKEY_USERS;
00090 }
00091
00092 m_hRoot = follow_path(m_hRoot, key.range(1, key.numsegments()), true, NULL);
00093
00094 #if 0
00095
00096
00097 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00098 RegNotifyChangeKeyValue(
00099 m_hRoot,
00100 TRUE,
00101 REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES |
00102 REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY,
00103 hEvent,
00104 TRUE
00105 );
00106 #endif
00107 }
00108
00109 UniRegistryGen::~UniRegistryGen()
00110 {
00111 if (m_hRoot)
00112 {
00113 RegCloseKey(m_hRoot);
00114 m_hRoot = 0;
00115 }
00116 }
00117
00118 bool UniRegistryGen::isok()
00119 {
00120 return m_hRoot != 0;
00121 }
00122
00123 WvString UniRegistryGen::get(const UniConfKey &key)
00124 {
00125 WvString retval = WvString::null;
00126 bool isvalue;
00127 HKEY hKey = follow_path(m_hRoot, key, false, &isvalue);
00128
00129 WvString value;
00130 if (isvalue)
00131 {
00132
00133 value = key.last();
00134 if (value == ".") value = WvString::null;
00135 }
00136 else
00137 {
00138
00139 value = WvString::null;
00140 }
00141
00142 DWORD type;
00143 TCHAR data[1024];
00144 DWORD size = sizeof(data) / sizeof(data[0]);
00145 LONG result = RegQueryValueEx(
00146 hKey,
00147 value.cstr(),
00148 0,
00149 &type,
00150 (BYTE *) data,
00151 &size
00152 );
00153
00154 if (result == ERROR_SUCCESS)
00155 {
00156 switch (type)
00157 {
00158 case REG_DWORD:
00159 retval.setsize(11);
00160 itoa(*((int *) data), retval.edit(), 10);
00161 break;
00162 case REG_SZ:
00163 retval = data;
00164 break;
00165 default:
00166 break;
00167 };
00168 }
00169
00170 if (hKey != m_hRoot) RegCloseKey(hKey);
00171 return retval;
00172 }
00173
00174 void UniRegistryGen::set(const UniConfKey &key, WvStringParm value)
00175 {
00176 LONG result;
00177 HKEY hKey = follow_path(m_hRoot, key.first( key.numsegments()-1 ), true, NULL);
00178 if (hKey)
00179 {
00180 if (value.isnull())
00181 {
00182 result = RegDeleteValue(hKey, key.last().printable());
00183 }
00184 else
00185 {
00186 WvString last = key.last();
00187 if (last == ".") last = WvString::null;
00188 result = RegSetValueEx(
00189 hKey,
00190 last,
00191 0,
00192 REG_SZ,
00193 (BYTE *) value.cstr(),
00194 strlen(value)+1
00195 );
00196 }
00197 if (result == ERROR_SUCCESS)
00198 {
00199 delta(key, value);
00200 }
00201 }
00202 if (hKey != m_hRoot) RegCloseKey(hKey);
00203 }
00204
00205 bool UniRegistryGen::exists(const UniConfKey &key)
00206 {
00207 return get(key) == WvString::null;
00208 }
00209
00210 bool UniRegistryGen::haschildren(const UniConfKey &key)
00211 {
00212 UniRegistryGenIter iter(*this, key, m_hRoot);
00213 iter.rewind();
00214 return iter.next();
00215 }
00216
00217
00218 UniConfGen::Iter *UniRegistryGen::iterator(const UniConfKey &key)
00219 {
00220 return new UniRegistryGenIter(*this, key, m_hRoot);
00221 }
00222
00223
00224 UniRegistryGenIter::UniRegistryGenIter(UniRegistryGen &gen,
00225 const UniConfKey &key, HKEY base)
00226 : m_hKey(0), m_enumerating(KEYS), m_index(0), gen(gen), parent(key),
00227 m_dontClose(base)
00228 {
00229 bool isValue;
00230 HKEY hKey = follow_path(base, key, false, &isValue);
00231
00232
00233
00234
00235 if (isValue)
00236 {
00237
00238 if (hKey != m_dontClose) RegCloseKey(hKey);
00239 m_enumerating = VALUES;
00240 }
00241 else
00242 m_hKey = hKey;
00243 }
00244
00245
00246 UniRegistryGenIter::~UniRegistryGenIter()
00247 {
00248 if (m_hKey && m_hKey != m_dontClose)
00249 RegCloseKey(m_hKey);
00250 }
00251
00252
00253 void UniRegistryGenIter::rewind()
00254 {
00255 current_key = "YOU HAVE TO REWIND, DUMMY!";
00256 m_enumerating = KEYS;
00257 m_index = 0;
00258 }
00259
00260
00261 bool UniRegistryGenIter::next()
00262 {
00263 if (m_enumerating == KEYS)
00264 {
00265 LONG result = next_key();
00266 if (result == ERROR_SUCCESS)
00267 return true;
00268 else if (result == ERROR_NO_MORE_ITEMS)
00269 {
00270
00271 m_enumerating = VALUES;
00272 m_index = 0;
00273 }
00274 else
00275 {
00276 fprintf(stderr, "KEY_ENUM result: %d\n", result);
00277 fflush(stderr);
00278 return false;
00279 }
00280 }
00281 assert(m_enumerating == VALUES);
00282 LONG result = next_value();
00283 if (result == ERROR_SUCCESS)
00284 return true;
00285 return false;
00286 }
00287
00288 UniConfKey UniRegistryGenIter::key() const
00289 {
00290 return current_key;
00291 }
00292
00293
00294 WvString UniRegistryGenIter::value() const
00295 {
00296 UniConfKey val(parent, current_key);
00297 return gen.get(val);
00298 }
00299
00300
00301 LONG UniRegistryGenIter::next_key()
00302 {
00303 if (!m_hKey)
00304 return ERROR_NO_MORE_ITEMS;
00305
00306 FILETIME dontcare;
00307 TCHAR data[1024];
00308 DWORD size = sizeof(data) / sizeof(data[0]);
00309 LONG result = RegEnumKeyEx(m_hKey, m_index++, data, &size, 0, 0, 0, &dontcare);
00310 if (result == ERROR_SUCCESS)
00311 current_key = data;
00312 return result;
00313 }
00314
00315
00316 LONG UniRegistryGenIter::next_value()
00317 {
00318 if (!m_hKey)
00319 return ERROR_NO_MORE_ITEMS;
00320
00321 TCHAR data[1024] = "";
00322 DWORD size = sizeof(data) / sizeof(data[0]);
00323 while (!*data)
00324 {
00325 LONG result = RegEnumValue(m_hKey, m_index++, data, &size, 0, 0, 0, 0);
00326 if (result != ERROR_SUCCESS)
00327 return result;
00328 }
00329 current_key = data;
00330 return ERROR_SUCCESS;
00331 }
00332
00333
00334 static IUniConfGen *creator(WvStringParm s, IObject *, void *)
00335 {
00336 return new UniRegistryGen(s);
00337 }
00338
00339 #pragma warning(disable : 4073)
00340 #pragma init_seg(lib)
00341 WvMoniker<IUniConfGen> UniRegistryGenMoniker("registry", creator);