- 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

This commit is contained in:
Guenter Obiltschnig
2008-09-18 09:04:17 +00:00
parent 707381faca
commit 14a4c61355
6 changed files with 137 additions and 44 deletions

View File

@@ -1,7 +1,7 @@
// //
// WinRegistryKey.h // 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 // Library: Util
// Package: Windows // Package: Windows
@@ -67,14 +67,22 @@ public:
REGT_DWORD = 4 REGT_DWORD = 4
}; };
WinRegistryKey(const std::string& key); WinRegistryKey(const std::string& key, bool readOnly = false);
/// Creates the WinRegistryKey. /// Creates the WinRegistryKey.
/// ///
/// The key must start with one of the root key names /// The key must start with one of the root key names
/// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. /// 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. /// 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(); ~WinRegistryKey();
/// Destroys the WinRegistryKey. /// Destroys the WinRegistryKey.
@@ -117,7 +125,7 @@ public:
/// Throws a NotFoundException if the value does not exist. /// Throws a NotFoundException if the value does not exist.
void deleteKey(); void deleteKey();
/// Deletes the key. The key must not have subkeys. /// Recursively deletes the key and all subkeys.
bool exists(); bool exists();
/// Returns true iff the key exists. /// Returns true iff the key exists.
@@ -133,6 +141,9 @@ public:
void values(Values& vals); void values(Values& vals);
/// Appends all value names to vals; /// Appends all value names to vals;
bool isReadOnly() const;
/// Returns true iff the key has been opened for read-only access only.
protected: protected:
void open(); void open();
@@ -150,9 +161,19 @@ private:
HKEY _hRootKey; HKEY _hRootKey;
std::string _subKey; std::string _subKey;
HKEY _hKey; HKEY _hKey;
bool _readOnly;
}; };
//
// inlines
//
inline bool WinRegistryKey::isReadOnly() const
{
return _readOnly;
}
} } // namespace Poco::Util } } // namespace Poco::Util

View File

@@ -1,7 +1,7 @@
// //
// WinRegistryConfiguration.cpp // WinRegistryConfiguration.cpp
// //
// $Id: //poco/svn/Util/src/WinRegistryConfiguration.cpp#1 $ // $Id: //poco/1.3/Util/src/WinRegistryConfiguration.cpp#3 $
// //
// Library: Util // Library: Util
// Package: Windows // Package: Windows
@@ -62,7 +62,7 @@ bool WinRegistryConfiguration::getRaw(const std::string& key, std::string& value
{ {
std::string keyName; std::string keyName;
std::string fullPath = _rootPath + ConvertToRegFormat(key, keyName); std::string fullPath = _rootPath + ConvertToRegFormat(key, keyName);
WinRegistryKey aKey(fullPath); WinRegistryKey aKey(fullPath, true);
bool exists = aKey.exists(keyName); bool exists = aKey.exists(keyName);
if (exists) if (exists)
{ {
@@ -112,7 +112,7 @@ void WinRegistryConfiguration::enumerate(const std::string& key, Keys& range) co
{ {
std::string keyName; std::string keyName;
std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName); std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName);
WinRegistryKey aKey(fullPath); WinRegistryKey aKey(fullPath, true);
aKey.values(range); aKey.values(range);
aKey.subKeys(range); aKey.subKeys(range);
} }

View File

@@ -1,7 +1,7 @@
// //
// WinRegistryKey.cpp // WinRegistryKey.cpp
// //
// $Id: //poco/svn/Util/src/WinRegistryKey.cpp#1 $ // $Id: //poco/1.3/Util/src/WinRegistryKey.cpp#5 $
// //
// Library: Util // Library: Util
// Package: Windows // Package: Windows
@@ -50,8 +50,9 @@ namespace Poco {
namespace Util { namespace Util {
WinRegistryKey::WinRegistryKey(const std::string& key): WinRegistryKey::WinRegistryKey(const std::string& key, bool readOnly):
_hKey(0) _hKey(0),
_readOnly(readOnly)
{ {
std::string::size_type pos = key.find('\\'); std::string::size_type pos = key.find('\\');
if (pos != std::string::npos) 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), _hRootKey(hRootKey),
_subKey(subKey), _subKey(subKey),
_hKey(0) _hKey(0),
_readOnly(readOnly)
{ {
} }
@@ -251,7 +253,17 @@ void WinRegistryKey::deleteValue(const std::string& name)
void WinRegistryKey::deleteKey() void WinRegistryKey::deleteKey()
{ {
Keys keys;
subKeys(keys);
close(); 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) #if defined(POCO_WIN32_UTF8)
std::wstring usubKey; std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, usubKey); Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
@@ -266,15 +278,23 @@ void WinRegistryKey::deleteKey()
bool WinRegistryKey::exists() bool WinRegistryKey::exists()
{ {
open(); HKEY hKey;
DWORD size;
#if defined(POCO_WIN32_UTF8) #if defined(POCO_WIN32_UTF8)
wchar_t name[256]; std::wstring usubKey;
return RegEnumValueW(_hKey, 0, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
RegCloseKey(hKey);
return true;
}
#else #else
char name[256]; if (RegOpenKeyEx(_hRootKey, _subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return RegEnumValue(_hKey, 0, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; {
RegCloseKey(hKey);
return true;
}
#endif #endif
return false;
} }
@@ -302,14 +322,26 @@ WinRegistryKey::Type WinRegistryKey::type(const std::string& name)
bool WinRegistryKey::exists(const std::string& name) bool WinRegistryKey::exists(const std::string& name)
{ {
open(); bool exists = false;
HKEY hKey;
#if defined(POCO_WIN32_UTF8) #if defined(POCO_WIN32_UTF8)
std::wstring uname; std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(name, uname); Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
return RegQueryValueExW(_hKey, uname.c_str(), NULL, NULL, NULL, NULL) == ERROR_SUCCESS; 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 #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 #endif
return exists;
} }
@@ -320,11 +352,27 @@ void WinRegistryKey::open()
#if defined(POCO_WIN32_UTF8) #if defined(POCO_WIN32_UTF8)
std::wstring usubKey; std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, 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) if (_readOnly)
throw SystemException("Cannot open registry key: ", key()); {
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 #else
if (RegCreateKeyEx(_hRootKey, _subKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hKey, NULL) != ERROR_SUCCESS) if (_readOnly)
throw SystemException("Cannot open registry key: ", key()); {
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 #endif
} }
} }

View File

@@ -1,7 +1,7 @@
// //
// UtilTestSuite.cpp // 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. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@@ -33,7 +33,7 @@
#include "UtilTestSuite.h" #include "UtilTestSuite.h"
#include "ConfigurationTestSuite.h" #include "ConfigurationTestSuite.h"
#include "OptionsTestSuite.h" #include "OptionsTestSuite.h"
#if defined(_MFC_VER) #if defined(_MSC_VER)
#include "WindowsTestSuite.h" #include "WindowsTestSuite.h"
#endif #endif
@@ -44,7 +44,7 @@ CppUnit::Test* UtilTestSuite::suite()
pSuite->addTest(ConfigurationTestSuite::suite()); pSuite->addTest(ConfigurationTestSuite::suite());
pSuite->addTest(OptionsTestSuite::suite()); pSuite->addTest(OptionsTestSuite::suite());
#if defined(_MFC_VER) #if defined(_MSC_VER)
pSuite->addTest(WindowsTestSuite::suite()); pSuite->addTest(WindowsTestSuite::suite());
#endif #endif

View File

@@ -1,7 +1,7 @@
// //
// WinConfigurationTest.cpp // 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. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@@ -55,18 +55,25 @@ WinConfigurationTest::~WinConfigurationTest()
void WinConfigurationTest::testConfiguration() void WinConfigurationTest::testConfiguration()
{ {
AutoPtr<WinRegistryConfiguration> reg = new WinRegistryConfiguration("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test"); AutoPtr<WinRegistryConfiguration> pReg = new WinRegistryConfiguration("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test");
reg->setString("name1", "value1"); pReg->setString("name1", "value1");
assert (reg->getString("name1") == "value1"); assert (pReg->getString("name1") == "value1");
reg->setInt("name1", 1); // overwrite should also change type pReg->setInt("name1", 1); // overwrite should also change type
assert (reg->getInt("name1") == 1); assert (pReg->getInt("name1") == 1);
reg->setString("name2", "value2"); pReg->setString("name2", "value2");
assert (reg->getString("name2") == "value2"); assert (pReg->getString("name2") == "value2");
assert (reg->hasProperty("name1")); assert (pReg->hasProperty("name1"));
assert (reg->hasProperty("name2")); assert (pReg->hasProperty("name2"));
std::string dfl = reg->getString("nonexistent", "default"); std::string dfl = pReg->getString("nonexistent", "default");
assert (dfl == "default"); assert (dfl == "default");
AutoPtr<Poco::Util::AbstractConfiguration> 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");
} }

View File

@@ -1,7 +1,7 @@
// //
// WinRegistryTest.cpp // 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. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@@ -35,6 +35,7 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/Util/WinRegistryKey.h" #include "Poco/Util/WinRegistryKey.h"
#include "Poco/Environment.h" #include "Poco/Environment.h"
#include "Poco/Exception.h"
using Poco::Util::WinRegistryKey; using Poco::Util::WinRegistryKey;
@@ -54,7 +55,11 @@ WinRegistryTest::~WinRegistryTest()
void WinRegistryTest::testRegistry() void WinRegistryTest::testRegistry()
{ {
WinRegistryKey regKey("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test"); WinRegistryKey regKey("HKEY_CURRENT_USER\\Software\\Applied Informatics\\Test");
regKey.deleteKey(); if (regKey.exists())
{
regKey.deleteKey();
}
assert (!regKey.exists());
regKey.setString("name1", "value1"); regKey.setString("name1", "value1");
assert (regKey.getString("name1") == "value1"); assert (regKey.getString("name1") == "value1");
regKey.setString("name1", "Value1"); regKey.setString("name1", "Value1");
@@ -64,7 +69,19 @@ void WinRegistryTest::testRegistry()
assert (regKey.exists("name1")); assert (regKey.exists("name1"));
assert (regKey.exists("name2")); assert (regKey.exists("name2"));
assert (regKey.exists()); 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; WinRegistryKey::Values vals;
regKey.values(vals); regKey.values(vals);
assert (vals.size() == 2); assert (vals.size() == 2);