From 14a4c61355472ed76fb398c4e81153d8c0dedb8f Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Thu, 18 Sep 2008 09:04:17 +0000 Subject: [PATCH] - fixed SF# 2012050: Configuration key created on read access; - Poco::Util::WinRegistryKey now has a read-only mode; - Poco::Util::WinRegistryKey::deleteKey() can now recursively delete registry keys --- Util/include/Poco/Util/WinRegistryKey.h | 29 ++++++- Util/src/WinRegistryConfiguration.cpp | 6 +- Util/src/WinRegistryKey.cpp | 88 ++++++++++++++++----- Util/testsuite/src/UtilTestSuite.cpp | 6 +- Util/testsuite/src/WinConfigurationTest.cpp | 29 ++++--- Util/testsuite/src/WinRegistryTest.cpp | 23 +++++- 6 files changed, 137 insertions(+), 44 deletions(-) diff --git a/Util/include/Poco/Util/WinRegistryKey.h b/Util/include/Poco/Util/WinRegistryKey.h index 1ddba7753..2a521ac94 100644 --- a/Util/include/Poco/Util/WinRegistryKey.h +++ b/Util/include/Poco/Util/WinRegistryKey.h @@ -1,7 +1,7 @@ // // WinRegistryKey.h // -// $Id: //poco/svn/Util/include/Poco/Util/WinRegistryKey.h#1 $ +// $Id: //poco/1.3/Util/include/Poco/Util/WinRegistryKey.h#2 $ // // Library: Util // Package: Windows @@ -67,14 +67,22 @@ public: REGT_DWORD = 4 }; - WinRegistryKey(const std::string& key); + WinRegistryKey(const std::string& key, bool readOnly = false); /// Creates the WinRegistryKey. /// /// The key must start with one of the root key names /// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. + /// + /// If readOnly is true, then only read access to the registry + /// is available and any attempt to write to the registry will + /// result in an exception. - WinRegistryKey(HKEY hRootKey, const std::string& subKey); + WinRegistryKey(HKEY hRootKey, const std::string& subKey, bool readOnly = false); /// Creates the WinRegistryKey. + /// + /// If readOnly is true, then only read access to the registry + /// is available and any attempt to write to the registry will + /// result in an exception. ~WinRegistryKey(); /// Destroys the WinRegistryKey. @@ -117,7 +125,7 @@ public: /// Throws a NotFoundException if the value does not exist. void deleteKey(); - /// Deletes the key. The key must not have subkeys. + /// Recursively deletes the key and all subkeys. bool exists(); /// Returns true iff the key exists. @@ -133,6 +141,9 @@ public: void values(Values& vals); /// Appends all value names to vals; + + bool isReadOnly() const; + /// Returns true iff the key has been opened for read-only access only. protected: void open(); @@ -150,9 +161,19 @@ private: HKEY _hRootKey; std::string _subKey; HKEY _hKey; + bool _readOnly; }; +// +// inlines +// +inline bool WinRegistryKey::isReadOnly() const +{ + return _readOnly; +} + + } } // namespace Poco::Util diff --git a/Util/src/WinRegistryConfiguration.cpp b/Util/src/WinRegistryConfiguration.cpp index 3b2b04d8c..a21904471 100644 --- a/Util/src/WinRegistryConfiguration.cpp +++ b/Util/src/WinRegistryConfiguration.cpp @@ -1,7 +1,7 @@ // // WinRegistryConfiguration.cpp // -// $Id: //poco/svn/Util/src/WinRegistryConfiguration.cpp#1 $ +// $Id: //poco/1.3/Util/src/WinRegistryConfiguration.cpp#3 $ // // Library: Util // Package: Windows @@ -62,7 +62,7 @@ bool WinRegistryConfiguration::getRaw(const std::string& key, std::string& value { std::string keyName; std::string fullPath = _rootPath + ConvertToRegFormat(key, keyName); - WinRegistryKey aKey(fullPath); + WinRegistryKey aKey(fullPath, true); bool exists = aKey.exists(keyName); if (exists) { @@ -112,7 +112,7 @@ void WinRegistryConfiguration::enumerate(const std::string& key, Keys& range) co { std::string keyName; std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName); - WinRegistryKey aKey(fullPath); + WinRegistryKey aKey(fullPath, true); aKey.values(range); aKey.subKeys(range); } diff --git a/Util/src/WinRegistryKey.cpp b/Util/src/WinRegistryKey.cpp index 55d327598..37882105e 100644 --- a/Util/src/WinRegistryKey.cpp +++ b/Util/src/WinRegistryKey.cpp @@ -1,7 +1,7 @@ // // WinRegistryKey.cpp // -// $Id: //poco/svn/Util/src/WinRegistryKey.cpp#1 $ +// $Id: //poco/1.3/Util/src/WinRegistryKey.cpp#5 $ // // Library: Util // Package: Windows @@ -50,8 +50,9 @@ namespace Poco { namespace Util { -WinRegistryKey::WinRegistryKey(const std::string& key): - _hKey(0) +WinRegistryKey::WinRegistryKey(const std::string& key, bool readOnly): + _hKey(0), + _readOnly(readOnly) { std::string::size_type pos = key.find('\\'); if (pos != std::string::npos) @@ -64,10 +65,11 @@ WinRegistryKey::WinRegistryKey(const std::string& key): } -WinRegistryKey::WinRegistryKey(HKEY hRootKey, const std::string& subKey): +WinRegistryKey::WinRegistryKey(HKEY hRootKey, const std::string& subKey, bool readOnly): _hRootKey(hRootKey), _subKey(subKey), - _hKey(0) + _hKey(0), + _readOnly(readOnly) { } @@ -251,7 +253,17 @@ void WinRegistryKey::deleteValue(const std::string& name) void WinRegistryKey::deleteKey() { + Keys keys; + subKeys(keys); close(); + for (Keys::iterator it = keys.begin(); it != keys.end(); ++it) + { + std::string subKey(_subKey); + subKey += "\\"; + subKey += *it; + WinRegistryKey subRegKey(_hRootKey, subKey); + subRegKey.deleteKey(); + } #if defined(POCO_WIN32_UTF8) std::wstring usubKey; Poco::UnicodeConverter::toUTF16(_subKey, usubKey); @@ -266,15 +278,23 @@ void WinRegistryKey::deleteKey() bool WinRegistryKey::exists() { - open(); - DWORD size; + HKEY hKey; #if defined(POCO_WIN32_UTF8) - wchar_t name[256]; - return RegEnumValueW(_hKey, 0, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + std::wstring usubKey; + Poco::UnicodeConverter::toUTF16(_subKey, usubKey); + if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + RegCloseKey(hKey); + return true; + } #else - char name[256]; - return RegEnumValue(_hKey, 0, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + if (RegOpenKeyEx(_hRootKey, _subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + return true; + } #endif + return false; } @@ -302,14 +322,26 @@ WinRegistryKey::Type WinRegistryKey::type(const std::string& name) bool WinRegistryKey::exists(const std::string& name) { - open(); + bool exists = false; + HKEY hKey; #if defined(POCO_WIN32_UTF8) - std::wstring uname; - Poco::UnicodeConverter::toUTF16(name, uname); - return RegQueryValueExW(_hKey, uname.c_str(), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + std::wstring usubKey; + Poco::UnicodeConverter::toUTF16(_subKey, usubKey); + if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + std::wstring uname; + Poco::UnicodeConverter::toUTF16(name, uname); + exists = RegQueryValueExW(hKey, uname.c_str(), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + RegCloseKey(hKey); + } #else - return RegQueryValueEx(_hKey, name.c_str(), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + if (RegOpenKeyEx(_hRootKey, _subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + exists = RegQueryValueEx(hKey, name.c_str(), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; + RegCloseKey(hKey); + } #endif + return exists; } @@ -320,11 +352,27 @@ void WinRegistryKey::open() #if defined(POCO_WIN32_UTF8) std::wstring usubKey; Poco::UnicodeConverter::toUTF16(_subKey, usubKey); - if (RegCreateKeyExW(_hRootKey, usubKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hKey, NULL) != ERROR_SUCCESS) - throw SystemException("Cannot open registry key: ", key()); + if (_readOnly) + { + if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ, &_hKey) != ERROR_SUCCESS) + throw NotFoundException("Cannot open registry key: ", key()); + } + else + { + if (RegCreateKeyExW(_hRootKey, usubKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hKey, NULL) != ERROR_SUCCESS) + throw SystemException("Cannot open registry key: ", key()); + } #else - if (RegCreateKeyEx(_hRootKey, _subKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hKey, NULL) != ERROR_SUCCESS) - throw SystemException("Cannot open registry key: ", key()); + if (_readOnly) + { + if (RegOpenKeyEx(_hRootKey, _subKey.c_str(), 0, KEY_READ, &_hKey) != ERROR_SUCCESS) + throw NotFoundException("Cannot open registry key: ", key()); + } + else + { + if (RegCreateKeyEx(_hRootKey, _subKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hKey, NULL) != ERROR_SUCCESS) + throw SystemException("Cannot open registry key: ", key()); + } #endif } } diff --git a/Util/testsuite/src/UtilTestSuite.cpp b/Util/testsuite/src/UtilTestSuite.cpp index 40f5f8aee..78403a61a 100644 --- a/Util/testsuite/src/UtilTestSuite.cpp +++ b/Util/testsuite/src/UtilTestSuite.cpp @@ -1,7 +1,7 @@ // // UtilTestSuite.cpp // -// $Id: //poco/svn/Util/testsuite/src/UtilTestSuite.cpp#1 $ +// $Id: //poco/1.3/Util/testsuite/src/UtilTestSuite.cpp#4 $ // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. @@ -33,7 +33,7 @@ #include "UtilTestSuite.h" #include "ConfigurationTestSuite.h" #include "OptionsTestSuite.h" -#if defined(_MFC_VER) +#if defined(_MSC_VER) #include "WindowsTestSuite.h" #endif @@ -44,7 +44,7 @@ CppUnit::Test* UtilTestSuite::suite() pSuite->addTest(ConfigurationTestSuite::suite()); pSuite->addTest(OptionsTestSuite::suite()); -#if defined(_MFC_VER) +#if defined(_MSC_VER) pSuite->addTest(WindowsTestSuite::suite()); #endif diff --git a/Util/testsuite/src/WinConfigurationTest.cpp b/Util/testsuite/src/WinConfigurationTest.cpp index f10c8accd..7e634e835 100644 --- a/Util/testsuite/src/WinConfigurationTest.cpp +++ b/Util/testsuite/src/WinConfigurationTest.cpp @@ -1,7 +1,7 @@ // // WinConfigurationTest.cpp // -// $Id: //poco/svn/Util/testsuite/src/WinConfigurationTest.cpp#1 $ +// $Id: //poco/1.3/Util/testsuite/src/WinConfigurationTest.cpp#2 $ // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. @@ -55,18 +55,25 @@ WinConfigurationTest::~WinConfigurationTest() void WinConfigurationTest::testConfiguration() { - AutoPtr reg = new WinRegistryConfiguration("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test"); - reg->setString("name1", "value1"); - assert (reg->getString("name1") == "value1"); - reg->setInt("name1", 1); // overwrite should also change type - assert (reg->getInt("name1") == 1); - reg->setString("name2", "value2"); - assert (reg->getString("name2") == "value2"); - assert (reg->hasProperty("name1")); - assert (reg->hasProperty("name2")); + AutoPtr pReg = new WinRegistryConfiguration("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test"); + pReg->setString("name1", "value1"); + assert (pReg->getString("name1") == "value1"); + pReg->setInt("name1", 1); // overwrite should also change type + assert (pReg->getInt("name1") == 1); + pReg->setString("name2", "value2"); + assert (pReg->getString("name2") == "value2"); + assert (pReg->hasProperty("name1")); + assert (pReg->hasProperty("name2")); - std::string dfl = reg->getString("nonexistent", "default"); + std::string dfl = pReg->getString("nonexistent", "default"); assert (dfl == "default"); + + AutoPtr pView = pReg->createView("config"); + dfl = pView->getString("sub.foo", "default"); + assert (dfl == "default"); + + pView->setString("sub.foo", "bar"); + assert (pView->getString("sub.foo", "default") == "bar"); } diff --git a/Util/testsuite/src/WinRegistryTest.cpp b/Util/testsuite/src/WinRegistryTest.cpp index 4f61525c4..24cd0bcab 100644 --- a/Util/testsuite/src/WinRegistryTest.cpp +++ b/Util/testsuite/src/WinRegistryTest.cpp @@ -1,7 +1,7 @@ // // WinRegistryTest.cpp // -// $Id: //poco/svn/Util/testsuite/src/WinRegistryTest.cpp#1 $ +// $Id: //poco/1.3/Util/testsuite/src/WinRegistryTest.cpp#1 $ // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. @@ -35,6 +35,7 @@ #include "CppUnit/TestSuite.h" #include "Poco/Util/WinRegistryKey.h" #include "Poco/Environment.h" +#include "Poco/Exception.h" using Poco::Util::WinRegistryKey; @@ -54,7 +55,11 @@ WinRegistryTest::~WinRegistryTest() void WinRegistryTest::testRegistry() { WinRegistryKey regKey("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test"); - regKey.deleteKey(); + if (regKey.exists()) + { + regKey.deleteKey(); + } + assert (!regKey.exists()); regKey.setString("name1", "value1"); assert (regKey.getString("name1") == "value1"); regKey.setString("name1", "Value1"); @@ -64,7 +69,19 @@ void WinRegistryTest::testRegistry() assert (regKey.exists("name1")); assert (regKey.exists("name2")); assert (regKey.exists()); - + + WinRegistryKey regKeyRO("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test", true); + assert (regKeyRO.getString("name1") == "Value1"); + try + { + regKeyRO.setString("name1", "newValue1"); + } + catch (Poco::Exception& exc) + { + std::string msg = exc.displayText(); + } + assert (regKey.getString("name1") == "Value1"); + WinRegistryKey::Values vals; regKey.values(vals); assert (vals.size() == 2);