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