xref: /third_party/lzma/CPP/Windows/Registry.cpp (revision 370b324c)
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
14extern bool g_IsNT;
15#endif
16
17namespace NWindows {
18namespace NRegistry {
19
20#define MYASSERT(expr) // _ASSERTE(expr)
21#define MY_ASSUME(expr)
22
23/*
24static 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
37LONG 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
56LONG 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
70LONG 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
83LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()
84{
85  MY_ASSUME(_object != NULL);
86  return RegDeleteKey(_object, subKeyName);
87}
88
89LONG 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
114static inline UInt32 BoolToUINT32(bool value) {  return (value ? 1: 0); }
115static inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }
116
117
118LONG CKey::DeleteValue(LPCTSTR name) throw()
119{
120  MY_ASSUME(_object != NULL);
121  return ::RegDeleteValue(_object, name);
122}
123
124#ifndef _UNICODE
125LONG 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
134LONG 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
141LONG CKey::SetValue(LPCTSTR name, bool value) throw()
142{
143  return SetValue(name, BoolToUINT32(value));
144}
145
146LONG 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/*
155LONG 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
166LONG 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
180LONG 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
188LONG 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
198LONG 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
208LONG 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
219LONG 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
227LONG 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
236LONG 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
245LONG 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
253LONG 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
272LONG 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
280LONG 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
312LONG 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
321LONG 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
332LONG 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
353LONG 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
375LONG 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