• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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