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
Create(HKEY parentKey,LPCTSTR keyName,LPTSTR keyClass,DWORD options,REGSAM accessMask,LPSECURITY_ATTRIBUTES securityAttributes,LPDWORD disposition)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
Open(HKEY parentKey,LPCTSTR keyName,REGSAM accessMask)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
Close()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
DeleteSubKey(LPCTSTR subKeyName)67 LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()
68 {
69 MYASSERT(_object != NULL);
70 return RegDeleteKey(_object, subKeyName);
71 }
72
RecurseDeleteKey(LPCTSTR subKeyName)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
BoolToUINT32(bool value)98 static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); }
UINT32ToBool(UInt32 value)99 static inline bool UINT32ToBool(UInt32 value) { return (value != 0); }
100
101
DeleteValue(LPCTSTR name)102 LONG CKey::DeleteValue(LPCTSTR name) throw()
103 {
104 MYASSERT(_object != NULL);
105 return ::RegDeleteValue(_object, name);
106 }
107
108 #ifndef _UNICODE
DeleteValue(LPCWSTR name)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
SetValue(LPCTSTR name,UInt32 value)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
SetValue(LPCTSTR name,bool value)125 LONG CKey::SetValue(LPCTSTR name, bool value) throw()
126 {
127 return SetValue(name, BoolToUINT32(value));
128 }
129
SetValue(LPCTSTR name,LPCTSTR value)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
SetValue(LPCWSTR name,LPCWSTR value)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, 0, 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
SetValue(LPCTSTR name,const void * value,UInt32 size)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
SetValue(HKEY parentKey,LPCTSTR keyName,LPCTSTR valueName,LPCTSTR value)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
SetKeyValue(LPCTSTR keyName,LPCTSTR valueName,LPCTSTR value)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
QueryValue(LPCTSTR name,UInt32 & value)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
QueryValue(LPCTSTR name,bool & value)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
GetValue_IfOk(LPCTSTR name,UInt32 & value)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
GetValue_IfOk(LPCTSTR name,bool & value)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
QueryValue(LPCTSTR name,LPTSTR value,UInt32 & count)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
QueryValue(LPCTSTR name,CSysString & value)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
QueryValue(LPCWSTR name,LPWSTR value,UInt32 & count)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
QueryValue(LPCWSTR name,UString & value)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
QueryValue(LPCTSTR name,void * value,UInt32 & count)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
QueryValue(LPCTSTR name,CByteBuffer & value,UInt32 & dataSize)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
EnumKeys(CSysStringVector & keyNames)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
SetValue_Strings(LPCTSTR valueName,const UStringVector & strings)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
GetValue_Strings(LPCTSTR valueName,UStringVector & strings)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