1 // Windows/Registry.cpp 2 3 #include "StdAfx.h" 4 5 #ifndef _UNICODE 6 #include "Common/StringConvert.h" 7 #endif 8 #include "Windows/Registry.h" 9 10 #ifndef _UNICODE 11 extern bool g_IsNT; 12 #endif 13 14 namespace NWindows { 15 namespace NRegistry { 16 17 #define MYASSERT(expr) // _ASSERTE(expr) 18 19 LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, 20 LPTSTR keyClass, DWORD options, REGSAM accessMask, 21 LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) 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 38 LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) 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 52 LONG CKey::Close() 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 65 LONG CKey::DeleteSubKey(LPCTSTR subKeyName) 66 { 67 MYASSERT(_object != NULL); 68 return RegDeleteKey(_object, subKeyName); 69 } 70 71 LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) 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 96 static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } 97 static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } 98 99 100 LONG CKey::DeleteValue(LPCTSTR name) 101 { 102 MYASSERT(_object != NULL); 103 return ::RegDeleteValue(_object, name); 104 } 105 106 #ifndef _UNICODE 107 LONG 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 116 LONG CKey::SetValue(LPCTSTR name, UInt32 value) 117 { 118 MYASSERT(_object != NULL); 119 return RegSetValueEx(_object, name, NULL, REG_DWORD, 120 (BYTE * const)&value, sizeof(UInt32)); 121 } 122 123 LONG CKey::SetValue(LPCTSTR name, bool value) 124 { 125 return SetValue(name, BoolToUINT32(value)); 126 } 127 128 LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) 129 { 130 MYASSERT(value != NULL); 131 MYASSERT(_object != NULL); 132 return RegSetValueEx(_object, name, NULL, REG_SZ, 133 (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); 134 } 135 136 /* 137 LONG 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.Length() + 1) * sizeof(TCHAR)); 143 } 144 */ 145 146 #ifndef _UNICODE 147 148 LONG 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 162 LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) 163 { 164 MYASSERT(value != NULL); 165 MYASSERT(_object != NULL); 166 return RegSetValueEx(_object, name, NULL, REG_BINARY, 167 (const BYTE *)value, size); 168 } 169 170 LONG 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 180 LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) 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 190 LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) 191 { 192 DWORD type = NULL; 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 201 LONG CKey::QueryValue(LPCTSTR name, bool &value) 202 { 203 UInt32 uintValue = BoolToUINT32(value); 204 LONG res = QueryValue(name, uintValue); 205 value = UINT32ToBool(uintValue); 206 return res; 207 } 208 209 LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) 210 { 211 UInt32 newVal; 212 LONG res = QueryValue(name, newVal); 213 if (res == ERROR_SUCCESS) 214 value = newVal; 215 return res; 216 } 217 218 LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) 219 { 220 bool newVal; 221 LONG res = QueryValue(name, newVal); 222 if (res == ERROR_SUCCESS) 223 value = newVal; 224 return res; 225 } 226 227 LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) 228 { 229 MYASSERT(count != NULL); 230 DWORD type = NULL; 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 236 LONG CKey::QueryValue(LPCTSTR name, CSysString &value) 237 { 238 value.Empty(); 239 DWORD type = NULL; 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 250 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) 251 { 252 MYASSERT(count != NULL); 253 DWORD type = NULL; 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 } 258 LONG CKey::QueryValue(LPCWSTR name, UString &value) 259 { 260 value.Empty(); 261 DWORD type = NULL; 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 283 LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) 284 { 285 DWORD type = NULL; 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 292 LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) 293 { 294 DWORD type = NULL; 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.SetCapacity(dataSize); 300 return QueryValue(name, (BYTE *)value, dataSize); 301 } 302 303 LONG 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 324 LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) 325 { 326 UInt32 numChars = 0; 327 int i; 328 for (i = 0; i < strings.Size(); i++) 329 numChars += strings[i].Length() + 1; 330 CBuffer<wchar_t> buffer; 331 buffer.SetCapacity(numChars); 332 int pos = 0; 333 for (i = 0; i < strings.Size(); i++) 334 { 335 const UString &s = strings[i]; 336 MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s); 337 pos += s.Length() + 1; 338 } 339 return SetValue(valueName, buffer, numChars * sizeof(wchar_t)); 340 } 341 342 LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) 343 { 344 strings.Clear(); 345 CByteBuffer buffer; 346 UInt32 dataSize; 347 LONG res = QueryValue(valueName, buffer, dataSize); 348 if (res != ERROR_SUCCESS) 349 return res; 350 if (dataSize % sizeof(wchar_t) != 0) 351 return E_FAIL; 352 const wchar_t *data = (const wchar_t *)(const Byte *)buffer; 353 int numChars = dataSize / sizeof(wchar_t); 354 UString s; 355 for (int i = 0; i < numChars; i++) 356 { 357 wchar_t c = data[i]; 358 if (c == 0) 359 { 360 strings.Add(s); 361 s.Empty(); 362 } 363 else 364 s += c; 365 } 366 return res; 367 } 368 369 }} 370