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