OSDN Git Service

Added enum_values() function to the Registry name-space.
[mutilities/MUtilities.git] / src / Registry_Win32.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 #pragma once
23
24 //MUtils
25 #include <MUtils/Registry.h>
26 #include <MUtils/Exception.h>
27
28 //Qt
29 #include <QStringList>
30
31 //Win32
32 #define WIN32_LEAN_AND_MEAN
33 #include <Windows.h>
34 #include <Shlwapi.h>
35
36 ///////////////////////////////////////////////////////////////////////////////
37
38 static HKEY registry_root(const int &rootKey)
39 {
40         switch(rootKey)
41         {
42                 case MUtils::Registry::root_classes: return HKEY_CLASSES_ROOT;  break;
43                 case MUtils::Registry::root_user:    return HKEY_CURRENT_USER;  break;
44                 case MUtils::Registry::root_machine: return HKEY_LOCAL_MACHINE; break;
45                 default: MUTILS_THROW("Unknown root reg value was specified!");
46         }
47 }
48
49 static DWORD registry_access(const int &access)
50 {
51         switch(access)
52         {
53                 case MUtils::Registry::access_readonly:  return KEY_READ;               break;
54                 case MUtils::Registry::access_writeonly: return KEY_WRITE;              break;
55                 case MUtils::Registry::access_readwrite: return KEY_READ | KEY_WRITE;   break;
56                 case MUtils::Registry::access_enumerate: return KEY_ENUMERATE_SUB_KEYS; break;
57                 default: MUTILS_THROW("Unknown access value was specified!");
58         }
59 }
60
61 ///////////////////////////////////////////////////////////////////////////////
62 // RegistryKeyPrivate Key Class
63 ///////////////////////////////////////////////////////////////////////////////
64
65 namespace MUtils
66 {
67         namespace Registry
68         {
69                 namespace Internal
70                 {
71                         class RegistryKeyPrivate
72                         {
73                                 friend class MUtils::Registry::RegistryKey;
74
75                         private:
76                                 HKEY  m_hKey;
77                                 DWORD m_access;
78                                 bool  m_isOpen;
79                         };
80                 }
81         }
82 }
83
84 #define CHECK_STATUS(X) do \
85 { \
86         if(!p->m_isOpen) \
87         { \
88                 MUTILS_THROW("Cannot read from or write to a key is not currently open!"); \
89         } \
90         if(!(p->m_access & (X))) \
91         { \
92                 MUTILS_THROW("This operation is not support with current access rights!"); \
93         } \
94 } \
95 while(0)
96
97 ///////////////////////////////////////////////////////////////////////////////
98 // Registry Key Class
99 ///////////////////////////////////////////////////////////////////////////////
100
101 MUtils::Registry::RegistryKey::RegistryKey(const int &rootKey, const QString &keyName, const int &access)
102 :
103         p(new Internal::RegistryKeyPrivate())
104 {
105         p->m_hKey   = NULL;
106         p->m_access = registry_access(access);
107         p->m_isOpen = false;
108
109         p->m_isOpen = (RegCreateKeyEx(registry_root(rootKey), MUTILS_WCHR(keyName), 0, NULL, 0, p->m_access, NULL, &p->m_hKey, NULL) == ERROR_SUCCESS);
110         if(!p->m_isOpen)
111         {
112                 qWarning("Failed to open registry key!");
113         }
114 }
115
116 MUtils::Registry::RegistryKey::~RegistryKey(void)
117 {
118         if(p->m_isOpen)
119         {
120                 CloseHandle(p->m_hKey);
121                 p->m_hKey = NULL;
122                 p->m_isOpen = false;
123         }
124         delete p;
125 }
126
127 inline bool MUtils::Registry::RegistryKey::isOpen(void)
128 {
129         return p->m_isOpen; 
130 }
131
132 bool MUtils::Registry::RegistryKey::value_write(const QString &valueName, const quint32 &value)
133 {
134         CHECK_STATUS(KEY_WRITE);
135         return (RegSetValueEx(p->m_hKey, valueName.isEmpty() ? NULL : MUTILS_WCHR(valueName), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(quint32)) == ERROR_SUCCESS);
136 }
137
138 bool MUtils::Registry::RegistryKey::value_write(const QString &valueName, const QString &value)
139 {
140         CHECK_STATUS(KEY_WRITE);
141         return (RegSetValueEx(p->m_hKey, valueName.isEmpty() ? NULL : MUTILS_WCHR(valueName), 0, REG_SZ, reinterpret_cast<const BYTE*>(value.utf16()), (value.length() + 1) * sizeof(wchar_t)) == ERROR_SUCCESS);
142 }
143
144 bool MUtils::Registry::RegistryKey::value_read(const QString &valueName, quint32 &value) const
145 {
146         value = 0;
147         DWORD size = sizeof(quint32), type = -1;
148         CHECK_STATUS(KEY_READ);
149         return (RegQueryValueEx(p->m_hKey, valueName.isEmpty() ? NULL : MUTILS_WCHR(valueName), 0, &type, reinterpret_cast<BYTE*>(&value), &size) == ERROR_SUCCESS) && (type == REG_DWORD);
150 }
151
152 bool MUtils::Registry::RegistryKey::value_read(const QString &valueName, QString &value) const
153 {
154         value = QString();
155         wchar_t buffer[2048]; DWORD size = sizeof(wchar_t) * 2048, type = -1;
156         CHECK_STATUS(KEY_READ);
157         if((RegQueryValueEx(p->m_hKey, valueName.isEmpty() ? NULL : MUTILS_WCHR(valueName), 0, &type, reinterpret_cast<BYTE*>(&(buffer[0])), &size) == ERROR_SUCCESS) && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
158         {
159                 value = QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
160                 return true;
161         }
162         return false;
163 }
164
165 bool MUtils::Registry::RegistryKey::enum_values(QStringList &list) const
166 {
167         wchar_t buffer[2048];
168         list.clear();
169         CHECK_STATUS(KEY_QUERY_VALUE);
170         for(DWORD i = 0; i < UINT_MAX; i++)
171         {
172                 DWORD size = 2048;
173                 const DWORD ret = RegEnumValue(p->m_hKey, i, buffer, &size, NULL, NULL, NULL, NULL);
174                 if(ret == ERROR_SUCCESS)
175                 {
176                         list << QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
177                         continue;
178                 }
179                 return (ret == ERROR_NO_MORE_ITEMS);
180         }
181         return false;
182 }
183
184 bool MUtils::Registry::RegistryKey::enum_subkeys(QStringList &list) const
185 {
186         wchar_t buffer[2048];
187         list.clear();
188         CHECK_STATUS(KEY_ENUMERATE_SUB_KEYS);
189         for(DWORD i = 0; i < UINT_MAX; i++)
190         {
191                 DWORD size = 2048;
192                 const DWORD ret = RegEnumKeyEx(p->m_hKey, i, buffer, &size, NULL, NULL, NULL, NULL);
193                 if(ret == ERROR_SUCCESS)
194                 {
195                         list << QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
196                         continue;
197                 }
198                 return (ret == ERROR_NO_MORE_ITEMS);
199         }
200         return false;
201 }
202
203 ///////////////////////////////////////////////////////////////////////////////
204 // HELPER FUNCTIONS
205 ///////////////////////////////////////////////////////////////////////////////
206
207 /*
208  * Write registry value
209  */
210 bool MUtils::Registry::reg_value_write(const int &rootKey, const QString &keyName, const QString &valueName, const quint32 &value)
211 {
212         bool success = false;
213         RegistryKey regKey(rootKey, keyName, access_readwrite);
214         if(regKey.isOpen())
215         {
216                 success = regKey.value_write(valueName, value);
217         }
218         return success;
219 }
220
221 /*
222  * Write registry value
223  */
224 bool MUtils::Registry::reg_value_write(const int &rootKey, const QString &keyName, const QString &valueName, const QString &value)
225 {
226         bool success = false;
227         RegistryKey regKey(rootKey, keyName, access_readwrite);
228         if(regKey.isOpen())
229         {
230                 success = regKey.value_write(valueName, value);
231         }
232         return success;
233 }
234
235 /*
236  * Read registry value
237  */
238 bool MUtils::Registry::reg_value_read(const int &rootKey, const QString &keyName, const QString &valueName, quint32 &value)
239 {
240         bool success = false;
241         RegistryKey regKey(rootKey, keyName, access_readonly);
242         if(regKey.isOpen())
243         {
244                 success = regKey.value_read(valueName, value);
245         }
246         else
247         {
248                 value = 0;
249         }
250         return success;
251 }
252
253 /*
254  * Read registry value
255  */
256 bool MUtils::Registry::reg_value_read(const int &rootKey, const QString &keyName, const QString &valueName, QString &value)
257 {
258         bool success = false;
259         RegistryKey regKey(rootKey, keyName, access_readonly);
260         if(regKey.isOpen())
261         {
262                 success = regKey.value_read(valueName, value);
263         }
264         else
265         {
266                 value = QString();
267         }
268         return success;
269 }
270
271 /*
272  * Enumerate value names
273  */
274 bool MUtils::Registry::reg_enum_values(const int &rootKey, const QString &keyName, QStringList &values)
275 {
276         bool success = false;
277         RegistryKey regKey(rootKey, keyName, access_readonly);
278         if(regKey.isOpen())
279         {
280                 success = regKey.enum_values(values);
281         }
282         else
283         {
284                 values.clear();
285         }
286         return success;
287 }
288
289 /*
290  * Enumerate subkey names
291  */
292 bool MUtils::Registry::reg_enum_subkeys(const int &rootKey, const QString &keyName, QStringList &subkeys)
293 {
294         bool success = false;
295         RegistryKey regKey(rootKey, keyName, access_enumerate);
296         if(regKey.isOpen())
297         {
298                 success = regKey.enum_subkeys(subkeys);
299         }
300         else
301         {
302                 subkeys.clear();
303         }
304         return success;
305 }
306
307 /*
308  * Delete registry key
309  */
310 bool MUtils::Registry::reg_key_delete(const int &rootKey, const QString &keyName)
311 {
312         return (SHDeleteKey(registry_root(rootKey), MUTILS_WCHR(keyName)) == ERROR_SUCCESS);
313 }