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
14 extern bool g_IsNT;
15 #endif
16
17 namespace NWindows {
18 namespace NRegistry {
19
20 #define MYASSERT(expr) // _ASSERTE(expr)
21 #define MY_ASSUME(expr)
22
23 /*
24 static 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
Create(HKEY parentKey,LPCTSTR keyName,LPTSTR keyClass,DWORD options,REGSAM accessMask,LPSECURITY_ATTRIBUTES securityAttributes,LPDWORD disposition)37 LONG 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
Open(HKEY parentKey,LPCTSTR keyName,REGSAM accessMask)56 LONG 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
Close()70 LONG 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
DeleteSubKey(LPCTSTR subKeyName)83 LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()
84 {
85 MY_ASSUME(_object != NULL);
86 return RegDeleteKey(_object, subKeyName);
87 }
88
RecurseDeleteKey(LPCTSTR subKeyName)89 LONG 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
BoolToUINT32(bool value)114 static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); }
UINT32ToBool(UInt32 value)115 static inline bool UINT32ToBool(UInt32 value) { return (value != 0); }
116
117
DeleteValue(LPCTSTR name)118 LONG CKey::DeleteValue(LPCTSTR name) throw()
119 {
120 MY_ASSUME(_object != NULL);
121 return ::RegDeleteValue(_object, name);
122 }
123
124 #ifndef _UNICODE
DeleteValue(LPCWSTR name)125 LONG 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
SetValue(LPCTSTR name,UInt32 value)134 LONG 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
SetValue(LPCTSTR name,bool value)141 LONG CKey::SetValue(LPCTSTR name, bool value) throw()
142 {
143 return SetValue(name, BoolToUINT32(value));
144 }
145
SetValue(LPCTSTR name,LPCTSTR value)146 LONG 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 /*
155 LONG 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
SetValue(LPCWSTR name,LPCWSTR value)166 LONG 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
SetValue(LPCTSTR name,const void * value,UInt32 size)180 LONG 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
SetValue(HKEY parentKey,LPCTSTR keyName,LPCTSTR valueName,LPCTSTR value)188 LONG 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
SetKeyValue(LPCTSTR keyName,LPCTSTR valueName,LPCTSTR value)198 LONG 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
QueryValue(LPCTSTR name,UInt32 & value)208 LONG 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
QueryValue(LPCTSTR name,bool & value)219 LONG 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
GetValue_IfOk(LPCTSTR name,UInt32 & value)227 LONG 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
GetValue_IfOk(LPCTSTR name,bool & value)236 LONG 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
QueryValue(LPCTSTR name,LPTSTR value,UInt32 & count)245 LONG 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
QueryValue(LPCTSTR name,CSysString & value)253 LONG 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
QueryValue(LPCWSTR name,LPWSTR value,UInt32 & count)272 LONG 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
QueryValue(LPCWSTR name,UString & value)280 LONG 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
QueryValue(LPCTSTR name,void * value,UInt32 & count)312 LONG 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
QueryValue(LPCTSTR name,CByteBuffer & value,UInt32 & dataSize)321 LONG 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
EnumKeys(CSysStringVector & keyNames)332 LONG 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
SetValue_Strings(LPCTSTR valueName,const UStringVector & strings)353 LONG 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
GetValue_Strings(LPCTSTR valueName,UStringVector & strings)375 LONG 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