Fixed is_library_file() for older Windows versions.
[MUtilities.git] / src / Registry_Win32.cpp
blob39c60abf67bc6d7c554a19ba3bc6f6d29ea99507
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 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.
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 //////////////////////////////////////////////////////////////////////////////////
22 #pragma once
24 //MUtils
25 #include <MUtils/Registry.h>
26 #include <MUtils/Exception.h>
28 //Qt
29 #include <QStringList>
31 //Win32
32 #define WIN32_LEAN_AND_MEAN
33 #include <Windows.h>
34 #include <Shlwapi.h>
36 ///////////////////////////////////////////////////////////////////////////////
37 // INTERNAL FUNCTIONS
38 ///////////////////////////////////////////////////////////////////////////////
40 #define ENUM2STR(X,Y) do \
41 { \
42 static const char *_name = #Y; \
43 if((X) == (Y)) return _name; \
44 } \
45 while(0)
47 namespace MUtils
49 namespace Registry
51 static HKEY registry_root(const reg_root_t &rootKey)
53 switch(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)
64 switch(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)
76 switch (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>";
92 return 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>";
103 return unknown;
108 ///////////////////////////////////////////////////////////////////////////////
109 // RegistryKeyPrivate Key Class
110 ///////////////////////////////////////////////////////////////////////////////
112 namespace MUtils
114 namespace Registry
116 namespace Internal
118 class RegistryKeyPrivate
120 friend class MUtils::Registry::RegistryKey;
122 private:
123 HKEY m_hKey;
124 DWORD m_access;
125 bool m_isOpen;
131 #define CHECK_STATUS(X) do \
133 if(!p->m_isOpen) \
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!"); \
142 while(0)
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())
152 p->m_hKey = NULL;
153 p->m_access = registry_access(access) | registry_scope(scope);
154 p->m_isOpen = false;
156 p->m_isOpen = (RegCreateKeyEx(registry_root(rootKey), MUTILS_WCHR(keyName), 0, NULL, 0, p->m_access, NULL, &p->m_hKey, NULL) == ERROR_SUCCESS);
157 if(!p->m_isOpen)
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)
165 if(p->m_isOpen)
167 CloseHandle(p->m_hKey);
168 p->m_hKey = NULL;
169 p->m_isOpen = false;
171 delete p;
174 inline bool MUtils::Registry::RegistryKey::isOpen(void)
176 return p->m_isOpen;
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
193 value = 0;
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
201 value = QString();
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));
207 return true;
209 return false;
212 bool MUtils::Registry::RegistryKey::enum_values(QStringList &list) const
214 wchar_t buffer[2048];
215 list.clear();
216 CHECK_STATUS(KEY_QUERY_VALUE);
217 for(DWORD i = 0; i < UINT_MAX; i++)
219 DWORD size = 2048;
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));
224 continue;
226 return (ret == ERROR_NO_MORE_ITEMS);
228 return false;
231 bool MUtils::Registry::RegistryKey::enum_subkeys(QStringList &list) const
233 wchar_t buffer[2048];
234 list.clear();
235 CHECK_STATUS(KEY_ENUMERATE_SUB_KEYS);
236 for(DWORD i = 0; i < UINT_MAX; i++)
238 DWORD size = 2048;
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));
243 continue;
245 return (ret == ERROR_NO_MORE_ITEMS);
247 return false;
250 ///////////////////////////////////////////////////////////////////////////////
251 // HELPER FUNCTIONS
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);
261 if(regKey.isOpen())
263 success = regKey.value_write(valueName, value);
265 return success;
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);
275 if(regKey.isOpen())
277 success = regKey.value_write(valueName, value);
279 return success;
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);
289 if(regKey.isOpen())
291 success = regKey.value_read(valueName, value);
293 else
295 value = 0;
297 return success;
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);
307 if(regKey.isOpen())
309 success = regKey.value_read(valueName, value);
311 else
313 value = QString();
315 return success;
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);
325 if(regKey.isOpen())
327 success = regKey.enum_values(values);
329 else
331 values.clear();
333 return success;
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);
343 if(regKey.isOpen())
345 success = regKey.enum_subkeys(subkeys);
347 else
349 subkeys.clear();
351 return success;
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)
359 HKEY hKey = NULL;
360 if(RegOpenKeyEx(registry_root(rootKey), MUTILS_WCHR(keyName), 0, STANDARD_RIGHTS_READ | registry_scope(scope), &hKey) == ERROR_SUCCESS)
362 RegCloseKey(hKey);
363 return true;
365 return false;
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)
373 bool okay = false;
375 if (scope != scope_default)
377 MUTILS_THROW("Scope option not currently supported by reg_key_delete() function!");
380 if(recusrive)
382 okay = (SHDeleteKey(registry_root(rootKey), MUTILS_WCHR(keyName)) == ERROR_SUCCESS);
384 else
386 okay = (RegDeleteKey(registry_root(rootKey), MUTILS_WCHR(keyName)) == ERROR_SUCCESS);
389 if(ascend && okay)
391 const int pos = qMax(keyName.lastIndexOf(QLatin1Char('/')), keyName.lastIndexOf(QLatin1Char('\\')));
392 if(pos > 0)
394 reg_key_delete(rootKey, keyName.left(pos), false, true);
398 return okay;