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 void UniRegistryGen::setv(const UniConfPairList &pairs)
00206 {
00207 setv_naive(pairs);
00208 }
00209
00210 bool UniRegistryGen::exists(const UniConfKey &key)
00211 {
00212 return !get(key).isnull();
00213 }
00214
00215 bool UniRegistryGen::haschildren(const UniConfKey &key)
00216 {
00217 UniRegistryGenIter iter(*this, key, m_hRoot);
00218 iter.rewind();
00219 return iter.next();
00220 }
00221
00222
00223 UniConfGen::Iter *UniRegistryGen::iterator(const UniConfKey &key)
00224 {
00225 return new UniRegistryGenIter(*this, key, m_hRoot);
00226 }
00227
00228
00229 UniRegistryGenIter::UniRegistryGenIter(UniRegistryGen &gen,
00230 const UniConfKey &key, HKEY base)
00231 : m_hKey(0), m_enumerating(KEYS), m_index(0), gen(gen), parent(key),
00232 m_dontClose(base)
00233 {
00234 bool isValue;
00235 HKEY hKey = follow_path(base, key, false, &isValue);
00236
00237
00238
00239
00240 if (isValue)
00241 {
00242
00243 if (hKey != m_dontClose) RegCloseKey(hKey);
00244 m_enumerating = VALUES;
00245 }
00246 else
00247 m_hKey = hKey;
00248 }
00249
00250
00251 UniRegistryGenIter::~UniRegistryGenIter()
00252 {
00253 if (m_hKey && m_hKey != m_dontClose)
00254 RegCloseKey(m_hKey);
00255 }
00256
00257
00258 void UniRegistryGenIter::rewind()
00259 {
00260 current_key = "YOU HAVE TO REWIND, DUMMY!";
00261 m_enumerating = KEYS;
00262 m_index = 0;
00263 }
00264
00265
00266 bool UniRegistryGenIter::next()
00267 {
00268 if (m_enumerating == KEYS)
00269 {
00270 LONG result = next_key();
00271 if (result == ERROR_SUCCESS)
00272 return true;
00273 else if (result == ERROR_NO_MORE_ITEMS)
00274 {
00275
00276 m_enumerating = VALUES;
00277 m_index = 0;
00278 }
00279 else
00280 {
00281 fprintf(stderr, "KEY_ENUM result: %ld\n", result);
00282 fflush(stderr);
00283 return false;
00284 }
00285 }
00286 assert(m_enumerating == VALUES);
00287 LONG result = next_value();
00288 if (result == ERROR_SUCCESS)
00289 return true;
00290 return false;
00291 }
00292
00293 UniConfKey UniRegistryGenIter::key() const
00294 {
00295 return current_key;
00296 }
00297
00298
00299 WvString UniRegistryGenIter::value() const
00300 {
00301 UniConfKey val(parent, current_key);
00302 return gen.get(val);
00303 }
00304
00305
00306 LONG UniRegistryGenIter::next_key()
00307 {
00308 if (!m_hKey)
00309 return ERROR_NO_MORE_ITEMS;
00310
00311 FILETIME dontcare;
00312 TCHAR data[1024];
00313 DWORD size = sizeof(data) / sizeof(data[0]);
00314 LONG result = RegEnumKeyEx(m_hKey, m_index++, data, &size, 0, 0, 0, &dontcare);
00315 if (result == ERROR_SUCCESS)
00316 current_key = data;
00317 return result;
00318 }
00319
00320
00321 LONG UniRegistryGenIter::next_value()
00322 {
00323 if (!m_hKey)
00324 return ERROR_NO_MORE_ITEMS;
00325
00326 TCHAR data[1024] = "";
00327 DWORD size = sizeof(data) / sizeof(data[0]);
00328 while (!*data)
00329 {
00330 LONG result = RegEnumValue(m_hKey, m_index++, data, &size, 0, 0, 0, 0);
00331 if (result != ERROR_SUCCESS)
00332 return result;
00333 }
00334 current_key = data;
00335 return ERROR_SUCCESS;
00336 }
00337
00338
00339 static IUniConfGen *creator(WvStringParm s, IObject*)
00340 {
00341 return new UniRegistryGen(s);
00342 }
00343
00344 #pragma warning(disable : 4073)
00345 #pragma init_seg(lib)
00346 WvMoniker<IUniConfGen> UniRegistryGenMoniker("registry", creator);