1 // Windows/Registry.cpp 2 3 #include "StdAfx.h" 4 5 #include <wchar.h> 6 7 #ifndef _UNICODE 8 #include "../Common/StringConvert.h" 9 #endif 10 #include "Registry.h" 11 12 #ifndef _UNICODE 13 extern bool g_IsNT; 14 #endif 15 16 namespace NWindows { 17 namespace NRegistry { 18 19 #define MYASSERT(expr) // _ASSERTE(expr) 20 21 LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, 22 LPTSTR keyClass, DWORD options, REGSAM accessMask, 23 LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw() 24 { 25 MYASSERT(parentKey != NULL); 26 DWORD dispositionReal; 27 HKEY key = NULL; 28 LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, 29 options, accessMask, securityAttributes, &key, &dispositionReal); 30 if (disposition != NULL) 31 *disposition = dispositionReal; 32 if (res == ERROR_SUCCESS) 33 { 34 res = Close(); 35 _object = key; 36 } 37 return res; 38 } 39 40 LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw() 41 { 42 MYASSERT(parentKey != NULL); 43 HKEY key = NULL; 44 LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); 45 if (res == ERROR_SUCCESS) 46 { 47 res = Close(); 48 MYASSERT(res == ERROR_SUCCESS); 49 _object = key; 50 } 51 return res; 52 } 53 54 LONG CKey::Close() throw() 55 { 56 LONG res = ERROR_SUCCESS; 57 if (_object != NULL) 58 { 59 res = RegCloseKey(_object); 60 _object = NULL; 61 } 62 return res; 63 } 64 65 // win95, win98: deletes sunkey and all its subkeys 66 // winNT to be deleted must not have subkeys 67 LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() 68 { 69 MYASSERT(_object != NULL); 70 return RegDeleteKey(_object, subKeyName); 71 } 72 73 LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() 74 { 75 CKey key; 76 LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); 77 if (res != ERROR_SUCCESS) 78 return res; 79 FILETIME fileTime; 80 const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL 81 DWORD size = kBufSize; 82 TCHAR buffer[kBufSize]; 83 while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) 84 { 85 res = key.RecurseDeleteKey(buffer); 86 if (res != ERROR_SUCCESS) 87 return res; 88 size = kBufSize; 89 } 90 key.Close(); 91 return DeleteSubKey(subKeyName); 92 } 93 94 95 ///////////////////////// 96 // Value Functions 97 98 static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } 99 static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } 100 101 102 LONG CKey::DeleteValue(LPCTSTR name) throw() 103 { 104 MYASSERT(_object != NULL); 105 return ::RegDeleteValue(_object, name); 106 } 107 108 #ifndef _UNICODE 109 LONG CKey::DeleteValue(LPCWSTR name) 110 { 111 MYASSERT(_object != NULL); 112 if (g_IsNT) 113 return ::RegDeleteValueW(_object, name); 114 return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); 115 } 116 #endif 117 118 LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw() 119 { 120 MYASSERT(_object != NULL); 121 return RegSetValueEx(_object, name, 0, REG_DWORD, 122 (BYTE * const)&value, sizeof(UInt32)); 123 } 124 125 LONG CKey::SetValue(LPCTSTR name, bool value) throw() 126 { 127 return SetValue(name, BoolToUINT32(value)); 128 } 129 130 LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() 131 { 132 MYASSERT(value != NULL); 133 MYASSERT(_object != NULL); 134 return RegSetValueEx(_object, name, 0, REG_SZ, 135 (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); 136 } 137 138 /* 139 LONG CKey::SetValue(LPCTSTR name, const CSysString &value) 140 { 141 MYASSERT(value != NULL); 142 MYASSERT(_object != NULL); 143 return RegSetValueEx(_object, name, NULL, REG_SZ, 144 (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); 145 } 146 */ 147 148 #ifndef _UNICODE 149 150 LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) 151 { 152 MYASSERT(value != NULL); 153 MYASSERT(_object != NULL); 154 if (g_IsNT) 155 return RegSetValueExW(_object, name, NULL, REG_SZ, 156 (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); 157 return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), 158 value == 0 ? 0 : (LPCSTR)GetSystemString(value)); 159 } 160 161 #endif 162 163 164 LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw() 165 { 166 MYASSERT(value != NULL); 167 MYASSERT(_object != NULL); 168 return RegSetValueEx(_object, name, 0, REG_BINARY, 169 (const BYTE *)value, size); 170 } 171 172 LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) 173 { 174 MYASSERT(value != NULL); 175 CKey key; 176 LONG res = key.Create(parentKey, keyName); 177 if (res == ERROR_SUCCESS) 178 res = key.SetValue(valueName, value); 179 return res; 180 } 181 182 LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw() 183 { 184 MYASSERT(value != NULL); 185 CKey key; 186 LONG res = key.Create(_object, keyName); 187 if (res == ERROR_SUCCESS) 188 res = key.SetValue(valueName, value); 189 return res; 190 } 191 192 LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() 193 { 194 DWORD type = 0; 195 DWORD count = sizeof(DWORD); 196 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, 197 (LPBYTE)&value, &count); 198 MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); 199 MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); 200 return res; 201 } 202 203 LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() 204 { 205 UInt32 uintValue = BoolToUINT32(value); 206 LONG res = QueryValue(name, uintValue); 207 value = UINT32ToBool(uintValue); 208 return res; 209 } 210 211 LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() 212 { 213 UInt32 newVal; 214 LONG res = QueryValue(name, newVal); 215 if (res == ERROR_SUCCESS) 216 value = newVal; 217 return res; 218 } 219 220 LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() 221 { 222 bool newVal; 223 LONG res = QueryValue(name, newVal); 224 if (res == ERROR_SUCCESS) 225 value = newVal; 226 return res; 227 } 228 229 LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() 230 { 231 DWORD type = 0; 232 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); 233 MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); 234 return res; 235 } 236 237 LONG CKey::QueryValue(LPCTSTR name, CSysString &value) 238 { 239 value.Empty(); 240 DWORD type = 0; 241 UInt32 curSize = 0; 242 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize); 243 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 244 return res; 245 UInt32 curSize2 = curSize; 246 res = QueryValue(name, value.GetBuf(curSize), curSize2); 247 if (curSize > curSize2) 248 curSize = curSize2; 249 value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); 250 return res; 251 } 252 253 254 #ifndef _UNICODE 255 256 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) 257 { 258 DWORD type = 0; 259 LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); 260 MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); 261 return res; 262 } 263 264 LONG CKey::QueryValue(LPCWSTR name, UString &value) 265 { 266 value.Empty(); 267 DWORD type = 0; 268 UInt32 curSize = 0; 269 270 LONG res; 271 272 if (g_IsNT) 273 { 274 res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize); 275 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 276 return res; 277 UInt32 curSize2 = curSize; 278 res = QueryValue(name, value.GetBuf(curSize), curSize2); 279 if (curSize > curSize2) 280 curSize = curSize2; 281 value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); 282 } 283 else 284 { 285 AString vTemp; 286 res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); 287 value = GetUnicodeString(vTemp); 288 } 289 290 return res; 291 } 292 293 #endif 294 295 296 LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() 297 { 298 DWORD type = 0; 299 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); 300 MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); 301 return res; 302 } 303 304 305 LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) 306 { 307 DWORD type = 0; 308 dataSize = 0; 309 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); 310 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 311 return res; 312 value.Alloc(dataSize); 313 return QueryValue(name, (BYTE *)value, dataSize); 314 } 315 316 LONG CKey::EnumKeys(CSysStringVector &keyNames) 317 { 318 keyNames.Clear(); 319 CSysString keyName; 320 for (DWORD index = 0; ; index++) 321 { 322 const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL 323 FILETIME lastWriteTime; 324 UInt32 nameSize = kBufSize; 325 LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), 326 (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); 327 keyName.ReleaseBuf_CalcLen(kBufSize); 328 if (result == ERROR_NO_MORE_ITEMS) 329 break; 330 if (result != ERROR_SUCCESS) 331 return result; 332 keyNames.Add(keyName); 333 } 334 return ERROR_SUCCESS; 335 } 336 337 LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) 338 { 339 size_t numChars = 0; 340 341 unsigned i; 342 343 for (i = 0; i < strings.Size(); i++) 344 numChars += strings[i].Len() + 1; 345 346 CObjArray<wchar_t> buffer(numChars); 347 size_t pos = 0; 348 349 for (i = 0; i < strings.Size(); i++) 350 { 351 const UString &s = strings[i]; 352 size_t size = s.Len() + 1; 353 wmemcpy(buffer + pos, s, size); 354 pos += size; 355 } 356 return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); 357 } 358 359 LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) 360 { 361 strings.Clear(); 362 CByteBuffer buffer; 363 UInt32 dataSize = 0; 364 LONG res = QueryValue(valueName, buffer, dataSize); 365 if (res != ERROR_SUCCESS) 366 return res; 367 if (dataSize > buffer.Size()) 368 return E_FAIL; 369 if (dataSize % sizeof(wchar_t) != 0) 370 return E_FAIL; 371 372 const wchar_t *data = (const wchar_t *)(const Byte *)buffer; 373 size_t numChars = dataSize / sizeof(wchar_t); 374 size_t prev = 0; 375 UString s; 376 377 for (size_t i = 0; i < numChars; i++) 378 { 379 if (data[i] == 0) 380 { 381 s = data + prev; 382 strings.Add(s); 383 prev = i + 1; 384 } 385 } 386 387 return res; 388 } 389 390 }} 391