1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
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.
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.
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
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
25 #include <MUtils/Registry.h>
26 #include <MUtils/Exception.h>
29 #include <QStringList>
32 #define WIN32_LEAN_AND_MEAN
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
40 #define ENUM2STR(X,Y) do \
42 static const char *_name = #Y; \
43 if((X) == (Y)) return _name; \
51 static HKEY
registry_root(const reg_root_t
&rootKey
)
55 case root_classes
: return HKEY_CLASSES_ROOT
; break;
56 case root_user
: return HKEY_CURRENT_USER
; break;
57 case root_machine
: return HKEY_LOCAL_MACHINE
; break;
58 default: MUTILS_THROW("Unknown root reg value was specified!");
62 static DWORD
registry_access(const reg_access_t
&access
)
66 case access_readonly
: return KEY_READ
; break;
67 case access_writeonly
: return KEY_WRITE
; break;
68 case access_readwrite
: return KEY_READ
| KEY_WRITE
; break;
69 case access_enumerate
: return KEY_ENUMERATE_SUB_KEYS
; break;
70 default: MUTILS_THROW("Unknown access value was specified!");
74 static DWORD
registry_scope(const reg_scope_t
&scope
)
78 case scope_default
: return 0; break;
79 case scope_wow_x32
: return KEY_WOW64_32KEY
; break;
80 case scope_wow_x64
: return KEY_WOW64_64KEY
; break;
81 default: MUTILS_THROW("Unknown scope value was specified!");
85 static const char* reg_root2str(const reg_root_t
&rootKey
)
87 ENUM2STR(rootKey
, root_classes
);
88 ENUM2STR(rootKey
, root_user
);
89 ENUM2STR(rootKey
, root_machine
);
91 static const char *unknown
= "<unknown>";
95 static const char* reg_access2str(const reg_access_t
&access
)
97 ENUM2STR(access
, access_readonly
);
98 ENUM2STR(access
, access_writeonly
);
99 ENUM2STR(access
, access_readwrite
);
100 ENUM2STR(access
, access_enumerate
);
102 static const char *unknown
= "<unknown>";
108 ///////////////////////////////////////////////////////////////////////////////
109 // RegistryKeyPrivate Key Class
110 ///////////////////////////////////////////////////////////////////////////////
118 class RegistryKeyPrivate
120 friend class MUtils::Registry::RegistryKey
;
131 #define CHECK_STATUS(X) do \
135 MUTILS_THROW("Cannot read from or write to a key is not currently open!"); \
137 if(!(p->m_access & (X))) \
139 MUTILS_THROW("This operation is not support with current access rights!"); \
144 ///////////////////////////////////////////////////////////////////////////////
145 // Registry Key Class
146 ///////////////////////////////////////////////////////////////////////////////
148 MUtils::Registry::RegistryKey::RegistryKey(const reg_root_t
&rootKey
, const QString
&keyName
, const reg_access_t
&access
, const reg_scope_t
&scope
)
150 p(new Internal::RegistryKeyPrivate())
153 p
->m_access
= registry_access(access
) | registry_scope(scope
);
156 p
->m_isOpen
= (RegCreateKeyEx(registry_root(rootKey
), MUTILS_WCHR(keyName
), 0, NULL
, 0, p
->m_access
, NULL
, &p
->m_hKey
, NULL
) == ERROR_SUCCESS
);
159 qWarning("Failed to open registry key \"%s\"! (rootKey: %s, access: %s)", MUTILS_UTF8(keyName
), reg_root2str(rootKey
), reg_access2str(access
));
163 MUtils::Registry::RegistryKey::~RegistryKey(void)
167 CloseHandle(p
->m_hKey
);
174 inline bool MUtils::Registry::RegistryKey::isOpen(void)
179 bool MUtils::Registry::RegistryKey::value_write(const QString
&valueName
, const quint32
&value
)
181 CHECK_STATUS(KEY_WRITE
);
182 return (RegSetValueEx(p
->m_hKey
, valueName
.isEmpty() ? NULL
: MUTILS_WCHR(valueName
), 0, REG_DWORD
, reinterpret_cast<const BYTE
*>(&value
), sizeof(quint32
)) == ERROR_SUCCESS
);
185 bool MUtils::Registry::RegistryKey::value_write(const QString
&valueName
, const QString
&value
)
187 CHECK_STATUS(KEY_WRITE
);
188 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
);
191 bool MUtils::Registry::RegistryKey::value_read(const QString
&valueName
, quint32
&value
) const
194 DWORD size
= sizeof(quint32
), type
= -1;
195 CHECK_STATUS(KEY_READ
);
196 return (RegQueryValueEx(p
->m_hKey
, valueName
.isEmpty() ? NULL
: MUTILS_WCHR(valueName
), 0, &type
, reinterpret_cast<BYTE
*>(&value
), &size
) == ERROR_SUCCESS
) && (type
== REG_DWORD
);
199 bool MUtils::Registry::RegistryKey::value_read(const QString
&valueName
, QString
&value
) const
202 wchar_t buffer
[2048]; DWORD size
= sizeof(wchar_t) * 2048, type
= -1;
203 CHECK_STATUS(KEY_READ
);
204 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
)))
206 value
= QString::fromUtf16(reinterpret_cast<const ushort
*>(buffer
));
212 bool MUtils::Registry::RegistryKey::enum_values(QStringList
&list
) const
214 wchar_t buffer
[2048];
216 CHECK_STATUS(KEY_QUERY_VALUE
);
217 for(DWORD i
= 0; i
< UINT_MAX
; i
++)
220 const DWORD ret
= RegEnumValue(p
->m_hKey
, i
, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
221 if(ret
== ERROR_SUCCESS
)
223 list
<< QString::fromUtf16(reinterpret_cast<const ushort
*>(buffer
));
226 return (ret
== ERROR_NO_MORE_ITEMS
);
231 bool MUtils::Registry::RegistryKey::enum_subkeys(QStringList
&list
) const
233 wchar_t buffer
[2048];
235 CHECK_STATUS(KEY_ENUMERATE_SUB_KEYS
);
236 for(DWORD i
= 0; i
< UINT_MAX
; i
++)
239 const DWORD ret
= RegEnumKeyEx(p
->m_hKey
, i
, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
240 if(ret
== ERROR_SUCCESS
)
242 list
<< QString::fromUtf16(reinterpret_cast<const ushort
*>(buffer
));
245 return (ret
== ERROR_NO_MORE_ITEMS
);
250 ///////////////////////////////////////////////////////////////////////////////
252 ///////////////////////////////////////////////////////////////////////////////
255 * Write registry value
257 bool MUtils::Registry::reg_value_write(const reg_root_t
&rootKey
, const QString
&keyName
, const QString
&valueName
, const quint32
&value
, const reg_scope_t
&scope
)
259 bool success
= false;
260 RegistryKey
regKey(rootKey
, keyName
, access_readwrite
, scope
);
263 success
= regKey
.value_write(valueName
, value
);
269 * Write registry value
271 bool MUtils::Registry::reg_value_write(const reg_root_t
&rootKey
, const QString
&keyName
, const QString
&valueName
, const QString
&value
, const reg_scope_t
&scope
)
273 bool success
= false;
274 RegistryKey
regKey(rootKey
, keyName
, access_readwrite
, scope
);
277 success
= regKey
.value_write(valueName
, value
);
283 * Read registry value
285 bool MUtils::Registry::reg_value_read(const reg_root_t
&rootKey
, const QString
&keyName
, const QString
&valueName
, quint32
&value
, const reg_scope_t
&scope
)
287 bool success
= false;
288 RegistryKey
regKey(rootKey
, keyName
, access_readonly
, scope
);
291 success
= regKey
.value_read(valueName
, value
);
301 * Read registry value
303 bool MUtils::Registry::reg_value_read(const reg_root_t
&rootKey
, const QString
&keyName
, const QString
&valueName
, QString
&value
, const reg_scope_t
&scope
)
305 bool success
= false;
306 RegistryKey
regKey(rootKey
, keyName
, access_readonly
, scope
);
309 success
= regKey
.value_read(valueName
, value
);
319 * Enumerate value names
321 bool MUtils::Registry::reg_enum_values(const reg_root_t
&rootKey
, const QString
&keyName
, QStringList
&values
, const reg_scope_t
&scope
)
323 bool success
= false;
324 RegistryKey
regKey(rootKey
, keyName
, access_readonly
, scope
);
327 success
= regKey
.enum_values(values
);
337 * Enumerate subkey names
339 bool MUtils::Registry::reg_enum_subkeys(const reg_root_t
&rootKey
, const QString
&keyName
, QStringList
&subkeys
, const reg_scope_t
&scope
)
341 bool success
= false;
342 RegistryKey
regKey(rootKey
, keyName
, access_enumerate
, scope
);
345 success
= regKey
.enum_subkeys(subkeys
);
355 * Check registry key existence
357 bool MUtils::Registry::reg_key_exists(const reg_root_t
&rootKey
, const QString
&keyName
, const reg_scope_t
&scope
)
360 if(RegOpenKeyEx(registry_root(rootKey
), MUTILS_WCHR(keyName
), 0, STANDARD_RIGHTS_READ
| registry_scope(scope
), &hKey
) == ERROR_SUCCESS
)
369 * Delete registry key
371 bool MUtils::Registry::reg_key_delete(const reg_root_t
&rootKey
, const QString
&keyName
, const bool &recusrive
, const bool &ascend
, const reg_scope_t
&scope
)
375 if (scope
!= scope_default
)
377 MUTILS_THROW("Scope option not currently supported by reg_key_delete() function!");
382 okay
= (SHDeleteKey(registry_root(rootKey
), MUTILS_WCHR(keyName
)) == ERROR_SUCCESS
);
386 okay
= (RegDeleteKey(registry_root(rootKey
), MUTILS_WCHR(keyName
)) == ERROR_SUCCESS
);
391 const int pos
= qMax(keyName
.lastIndexOf(QLatin1Char('/')), keyName
.lastIndexOf(QLatin1Char('\\')));
394 reg_key_delete(rootKey
, keyName
.left(pos
), false, true);