1 // Windows/Registry.cpp
\r
6 #include "Common/StringConvert.h"
\r
8 #include "Windows/Registry.h"
\r
14 namespace NWindows {
\r
15 namespace NRegistry {
\r
17 #define MYASSERT(expr) // _ASSERTE(expr)
\r
19 LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,
\r
20 LPTSTR keyClass, DWORD options, REGSAM accessMask,
\r
21 LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition)
\r
23 MYASSERT(parentKey != NULL);
\r
24 DWORD dispositionReal;
\r
26 LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,
\r
27 options, accessMask, securityAttributes, &key, &dispositionReal);
\r
28 if (disposition != NULL)
\r
29 *disposition = dispositionReal;
\r
30 if (res == ERROR_SUCCESS)
\r
38 LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask)
\r
40 MYASSERT(parentKey != NULL);
\r
42 LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);
\r
43 if (res == ERROR_SUCCESS)
\r
46 MYASSERT(res == ERROR_SUCCESS);
\r
54 LONG res = ERROR_SUCCESS;
\r
55 if (_object != NULL)
\r
57 res = RegCloseKey(_object);
\r
63 // win95, win98: deletes sunkey and all its subkeys
\r
64 // winNT to be deleted must not have subkeys
\r
65 LONG CKey::DeleteSubKey(LPCTSTR subKeyName)
\r
67 MYASSERT(_object != NULL);
\r
68 return RegDeleteKey(_object, subKeyName);
\r
71 LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName)
\r
74 LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);
\r
75 if (res != ERROR_SUCCESS)
\r
78 const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
\r
79 DWORD size = kBufferSize;
\r
80 TCHAR buffer[kBufferSize];
\r
81 while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)
\r
83 res = key.RecurseDeleteKey(buffer);
\r
84 if (res != ERROR_SUCCESS)
\r
89 return DeleteSubKey(subKeyName);
\r
93 /////////////////////////
\r
96 static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); }
\r
97 static inline bool UINT32ToBool(UInt32 value) { return (value != 0); }
\r
100 LONG CKey::DeleteValue(LPCTSTR name)
\r
102 MYASSERT(_object != NULL);
\r
103 return ::RegDeleteValue(_object, name);
\r
107 LONG CKey::DeleteValue(LPCWSTR name)
\r
109 MYASSERT(_object != NULL);
\r
111 return ::RegDeleteValueW(_object, name);
\r
112 return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name));
\r
116 LONG CKey::SetValue(LPCTSTR name, UInt32 value)
\r
118 MYASSERT(_object != NULL);
\r
119 return RegSetValueEx(_object, name, NULL, REG_DWORD,
\r
120 (BYTE * const)&value, sizeof(UInt32));
\r
123 LONG CKey::SetValue(LPCTSTR name, bool value)
\r
125 return SetValue(name, BoolToUINT32(value));
\r
128 LONG CKey::SetValue(LPCTSTR name, LPCTSTR value)
\r
130 MYASSERT(value != NULL);
\r
131 MYASSERT(_object != NULL);
\r
132 return RegSetValueEx(_object, name, NULL, REG_SZ,
\r
133 (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));
\r
137 LONG CKey::SetValue(LPCTSTR name, const CSysString &value)
\r
139 MYASSERT(value != NULL);
\r
140 MYASSERT(_object != NULL);
\r
141 return RegSetValueEx(_object, name, NULL, REG_SZ,
\r
142 (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR));
\r
148 LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)
\r
150 MYASSERT(value != NULL);
\r
151 MYASSERT(_object != NULL);
\r
153 return RegSetValueExW(_object, name, NULL, REG_SZ,
\r
154 (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));
\r
155 return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),
\r
156 value == 0 ? 0 : (LPCSTR)GetSystemString(value));
\r
162 LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size)
\r
164 MYASSERT(value != NULL);
\r
165 MYASSERT(_object != NULL);
\r
166 return RegSetValueEx(_object, name, NULL, REG_BINARY,
\r
167 (const BYTE *)value, size);
\r
170 LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)
\r
172 MYASSERT(value != NULL);
\r
174 LONG res = key.Create(parentKey, keyName);
\r
175 if (res == ERROR_SUCCESS)
\r
176 res = key.SetValue(valueName, value);
\r
180 LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)
\r
182 MYASSERT(value != NULL);
\r
184 LONG res = key.Create(_object, keyName);
\r
185 if (res == ERROR_SUCCESS)
\r
186 res = key.SetValue(valueName, value);
\r
190 LONG CKey::QueryValue(LPCTSTR name, UInt32 &value)
\r
193 DWORD count = sizeof(DWORD);
\r
194 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,
\r
195 (LPBYTE)&value, &count);
\r
196 MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD));
\r
197 MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32)));
\r
201 LONG CKey::QueryValue(LPCTSTR name, bool &value)
\r
203 UInt32 uintValue = BoolToUINT32(value);
\r
204 LONG res = QueryValue(name, uintValue);
\r
205 value = UINT32ToBool(uintValue);
\r
209 LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value)
\r
212 LONG res = QueryValue(name, newVal);
\r
213 if (res == ERROR_SUCCESS)
\r
218 LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value)
\r
221 LONG res = QueryValue(name, newVal);
\r
222 if (res == ERROR_SUCCESS)
\r
227 LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count)
\r
229 MYASSERT(count != NULL);
\r
231 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
\r
232 MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
\r
236 LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
\r
240 UInt32 currentSize = 0;
\r
241 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)¤tSize);
\r
242 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
\r
244 res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
\r
245 value.ReleaseBuffer();
\r
250 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)
\r
252 MYASSERT(count != NULL);
\r
254 LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
\r
255 MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
\r
258 LONG CKey::QueryValue(LPCWSTR name, UString &value)
\r
262 UInt32 currentSize = 0;
\r
267 res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)¤tSize);
\r
268 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
\r
270 res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
\r
271 value.ReleaseBuffer();
\r
276 res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
\r
277 value = GetUnicodeString(vTemp);
\r
283 LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count)
\r
286 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
\r
287 MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY));
\r
292 LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)
\r
296 LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);
\r
297 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
\r
299 value.SetCapacity(dataSize);
\r
300 return QueryValue(name, (BYTE *)value, dataSize);
\r
303 LONG CKey::EnumKeys(CSysStringVector &keyNames)
\r
306 CSysString keyName;
\r
307 for (UInt32 index = 0; ; index++)
\r
309 const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
\r
310 FILETIME lastWriteTime;
\r
311 UInt32 nameSize = kBufferSize;
\r
312 LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),
\r
313 (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);
\r
314 keyName.ReleaseBuffer();
\r
315 if (result == ERROR_NO_MORE_ITEMS)
\r
317 if (result != ERROR_SUCCESS)
\r
319 keyNames.Add(keyName);
\r
321 return ERROR_SUCCESS;
\r
324 LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)
\r
326 UInt32 numChars = 0;
\r
328 for (i = 0; i < strings.Size(); i++)
\r
329 numChars += strings[i].Length() + 1;
\r
330 CBuffer<wchar_t> buffer;
\r
331 buffer.SetCapacity(numChars);
\r
333 for (i = 0; i < strings.Size(); i++)
\r
335 const UString &s = strings[i];
\r
336 MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);
\r
337 pos += s.Length() + 1;
\r
339 return SetValue(valueName, buffer, numChars * sizeof(wchar_t));
\r
342 LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
\r
345 CByteBuffer buffer;
\r
347 LONG res = QueryValue(valueName, buffer, dataSize);
\r
348 if (res != ERROR_SUCCESS)
\r
350 if (dataSize % sizeof(wchar_t) != 0)
\r
352 const wchar_t *data = (const wchar_t *)(const Byte *)buffer;
\r
353 int numChars = dataSize / sizeof(wchar_t);
\r
355 for (int i = 0; i < numChars; i++)
\r
357 wchar_t c = data[i];
\r