diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/Windows/Registry.cpp | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp new file mode 100644 index 0000000..b20157d --- /dev/null +++ b/CPP/Windows/Registry.cpp | |||
@@ -0,0 +1,406 @@ | |||
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 | |||
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 | |||
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 | |||
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 | ||
83 | LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() | ||
84 | { | ||
85 | MY_ASSUME(_object != NULL); | ||
86 | return RegDeleteKey(_object, subKeyName); | ||
87 | } | ||
88 | |||
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 | |||
114 | static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } | ||
115 | static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } | ||
116 | |||
117 | |||
118 | LONG CKey::DeleteValue(LPCTSTR name) throw() | ||
119 | { | ||
120 | MY_ASSUME(_object != NULL); | ||
121 | return ::RegDeleteValue(_object, name); | ||
122 | } | ||
123 | |||
124 | #ifndef _UNICODE | ||
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 | |||
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 | |||
141 | LONG CKey::SetValue(LPCTSTR name, bool value) throw() | ||
142 | { | ||
143 | return SetValue(name, BoolToUINT32(value)); | ||
144 | } | ||
145 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | }} | ||