poco/Util/src/WinRegistryKey.cpp
Kari Argillander 708a5d8307
RFC: Remove Windows CE support (#4342)
* Remove _WIN32_WCE macro

Poco now use C++17 and Windows CE does not support it and VS2017 does
also not support it so we can just remove Windows CE code. First remove
all macro usages from our own files.

* Remove WinCE support from build files

Poco now use C++17 and Windows CE does not support it and VS2017 does
also not support it so we can just remove Windows CE code. Remove all
references from build systems / scripts.

* Remove Windows CE related source and header files

Poco now use C++17 and Windows CE does not support it and VS2017 does
also not support it so we can just remove Windows CE code. First remove
all macro usages from our own files.

* Remove wcelibcex folder

Poco now use C++17 and Windows CE does not support it and VS2017 does
also not support it so we can just remove Windows CE code. First remove
all macro usages from our own files.

* Remove rest Windows CE mentions

There where some Windows CE mentions left. Remove those.

* Update Windows CE documentation

We should keep documentation some time so people can find reason for
remove.

---------

Co-authored-by: Kari Argillander <kari.argillander@fidelix.com>
2023-12-14 00:25:04 +01:00

506 lines
12 KiB
C++

//
// WinRegistryKey.cpp
//
// Library: Util
// Package: Windows
// Module: WinRegistryKey
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Util/WinRegistryKey.h"
#include "Poco/Exception.h"
#include "Poco/Buffer.h"
#include "Poco/UnicodeConverter.h"
using Poco::SystemException;
using Poco::NotFoundException;
using Poco::InvalidArgumentException;
namespace Poco {
namespace Util {
namespace
{
class AutoHandle
{
public:
AutoHandle(HMODULE h):
_h(h)
{
}
~AutoHandle()
{
FreeLibrary(_h);
}
HMODULE handle()
{
return _h;
}
private:
HMODULE _h;
};
}
WinRegistryKey::WinRegistryKey(const std::string& key, bool readOnly, REGSAM extraSam):
_hKey(0),
_readOnly(readOnly),
_extraSam(extraSam)
{
std::string::size_type pos = key.find('\\');
if (pos != std::string::npos)
{
std::string rootKey = key.substr(0, pos);
_hRootKey = handleFor(rootKey);
_subKey = key.substr(pos + 1);
}
else throw InvalidArgumentException("Not a valid registry key", key);
}
WinRegistryKey::WinRegistryKey(HKEY hRootKey, const std::string& subKey, bool readOnly, REGSAM extraSam):
_hRootKey(hRootKey),
_subKey(subKey),
_hKey(0),
_readOnly(readOnly),
_extraSam(extraSam)
{
}
WinRegistryKey::~WinRegistryKey()
{
close();
}
void WinRegistryKey::setString(const std::string& name, const std::string& value)
{
open();
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
std::wstring uvalue;
Poco::UnicodeConverter::toUTF16(value, uvalue);
if (RegSetValueExW(_hKey, uname.c_str(), 0, REG_SZ, (CONST BYTE*) uvalue.c_str(), (DWORD) (uvalue.size() + 1)*sizeof(wchar_t)) != ERROR_SUCCESS)
handleSetError(name);
}
std::string WinRegistryKey::getString(const std::string& name)
{
open();
DWORD type;
DWORD size;
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, NULL, &size) != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_LINK))
throw NotFoundException(key(name));
if (size > 0)
{
DWORD len = size/2;
Poco::Buffer<wchar_t> buffer(len + 1);
RegQueryValueExW(_hKey, uname.c_str(), NULL, NULL, (BYTE*) buffer.begin(), &size);
buffer[len] = 0;
std::wstring uresult(buffer.begin());
std::string result;
Poco::UnicodeConverter::toUTF8(uresult, result);
return result;
}
return std::string();
}
void WinRegistryKey::setStringExpand(const std::string& name, const std::string& value)
{
open();
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
std::wstring uvalue;
Poco::UnicodeConverter::toUTF16(value, uvalue);
if (RegSetValueExW(_hKey, uname.c_str(), 0, REG_EXPAND_SZ, (CONST BYTE*) uvalue.c_str(), (DWORD) (uvalue.size() + 1)*sizeof(wchar_t)) != ERROR_SUCCESS)
handleSetError(name);
}
std::string WinRegistryKey::getStringExpand(const std::string& name)
{
open();
DWORD type;
DWORD size;
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, NULL, &size) != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_LINK))
throw NotFoundException(key(name));
if (size > 0)
{
DWORD len = size/2;
Poco::Buffer<wchar_t> buffer(len + 1);
RegQueryValueExW(_hKey, uname.c_str(), NULL, NULL, (BYTE*) buffer.begin(), &size);
buffer[len] = 0;
wchar_t temp;
DWORD expSize = ExpandEnvironmentStringsW(buffer.begin(), &temp, 1);
Poco::Buffer<wchar_t> expBuffer(expSize);
ExpandEnvironmentStringsW(buffer.begin(), expBuffer.begin(), expSize);
std::string result;
UnicodeConverter::toUTF8(expBuffer.begin(), result);
return result;
}
return std::string();
}
void WinRegistryKey::setBinary( const std::string& name, const std::vector<char>& value )
{
open();
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegSetValueExW(_hKey, uname.c_str(), 0, REG_BINARY, (CONST BYTE*) &value[0], (DWORD) value.size()) != ERROR_SUCCESS)
handleSetError(name);
}
std::vector<char> WinRegistryKey::getBinary( const std::string& name )
{
open();
DWORD type;
DWORD size;
std::vector<char> result;
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, NULL, &size) != ERROR_SUCCESS || type != REG_BINARY)
throw NotFoundException(key(name));
if (size > 0)
{
result.resize(size);
RegQueryValueExW(_hKey, uname.c_str(), NULL, NULL, (BYTE*) &result[0], &size);
}
return result;
}
void WinRegistryKey::setInt(const std::string& name, int value)
{
open();
DWORD data = value;
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegSetValueExW(_hKey, uname.c_str(), 0, REG_DWORD, (CONST BYTE*) &data, sizeof(data)) != ERROR_SUCCESS)
handleSetError(name);
}
int WinRegistryKey::getInt(const std::string& name)
{
open();
DWORD type;
DWORD data;
DWORD size = sizeof(data);
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, (BYTE*) &data, &size) != ERROR_SUCCESS || (type != REG_DWORD && type != REG_DWORD_BIG_ENDIAN))
throw NotFoundException(key(name));
return data;
}
#if defined(POCO_HAVE_INT64)
void WinRegistryKey::setInt64(const std::string& name, Poco::Int64 value)
{
open();
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegSetValueExW(_hKey, uname.c_str(), 0, REG_QWORD, (CONST BYTE*) &value, sizeof(value)) != ERROR_SUCCESS)
handleSetError(name);
}
Poco::Int64 WinRegistryKey::getInt64(const std::string& name)
{
open();
DWORD type;
Poco::Int64 data;
DWORD size = sizeof(data);
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, (BYTE*) &data, &size) != ERROR_SUCCESS || type != REG_QWORD)
throw NotFoundException(key(name));
return data;
}
#endif // POCO_HAVE_INT64
void WinRegistryKey::deleteValue(const std::string& name)
{
open();
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegDeleteValueW(_hKey, uname.c_str()) != ERROR_SUCCESS)
throw NotFoundException(key(name));
}
void WinRegistryKey::deleteKey()
{
Keys keys;
subKeys(keys);
close();
for (const auto& k: keys)
{
std::string subKey(_subKey);
subKey += "\\";
subKey += k;
WinRegistryKey subRegKey(_hRootKey, subKey, _readOnly, _extraSam);
subRegKey.deleteKey();
}
// NOTE: RegDeleteKeyEx is only available on Windows XP 64-bit SP3, Windows Vista or later.
// We cannot call it directly as this would prevent the code running on Windows XP 32-bit.
// Therefore, if we need to call RegDeleteKeyEx (_extraSam != 0) we need to check for
// its existence in ADVAPI32.DLL and call it indirectly.
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
typedef LONG (WINAPI *RegDeleteKeyExWFunc)(HKEY hKey, const wchar_t* lpSubKey, REGSAM samDesired, DWORD Reserved);
if (_extraSam != 0)
{
AutoHandle advAPI32(LoadLibraryW(L"ADVAPI32.DLL"));
if (advAPI32.handle())
{
RegDeleteKeyExWFunc pRegDeleteKeyExW = reinterpret_cast<RegDeleteKeyExWFunc>(GetProcAddress(advAPI32.handle() , "RegDeleteKeyExW"));
if (pRegDeleteKeyExW)
{
if ((*pRegDeleteKeyExW)(_hRootKey, usubKey.c_str(), _extraSam, 0) != ERROR_SUCCESS)
throw NotFoundException(key());
return;
}
}
}
if (RegDeleteKeyW(_hRootKey, usubKey.c_str()) != ERROR_SUCCESS)
throw NotFoundException(key());
}
bool WinRegistryKey::exists()
{
HKEY hKey;
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ | _extraSam, &hKey) == ERROR_SUCCESS)
{
RegCloseKey(hKey);
return true;
}
return false;
}
WinRegistryKey::Type WinRegistryKey::type(const std::string& name)
{
open();
DWORD type = REG_NONE;
DWORD size;
std::wstring uname;
Poco::UnicodeConverter::toUTF16(name, uname);
if (RegQueryValueExW(_hKey, uname.c_str(), NULL, &type, NULL, &size) != ERROR_SUCCESS)
throw NotFoundException(key(name));
Type aType = (Type)type;
return aType;
}
bool WinRegistryKey::exists(const std::string& name)
{
bool exists = false;
HKEY hKey;
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ | _extraSam, &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);
}
return exists;
}
void WinRegistryKey::open()
{
if (!_hKey)
{
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(_subKey, usubKey);
if (_readOnly)
{
if (RegOpenKeyExW(_hRootKey, usubKey.c_str(), 0, KEY_READ | _extraSam, &_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 | _extraSam, NULL, &_hKey, NULL) != ERROR_SUCCESS)
throw SystemException("Cannot open registry key: ", key());
}
}
}
void WinRegistryKey::close()
{
if (_hKey)
{
RegCloseKey(_hKey);
_hKey = 0;
}
}
std::string WinRegistryKey::key() const
{
std::string result;
if (_hRootKey == HKEY_CLASSES_ROOT)
result = "HKEY_CLASSES_ROOT";
#if defined(HKEY_CURRENT_CONFIG)
else if (_hRootKey == HKEY_CURRENT_CONFIG)
result = "HKEY_CURRENT_CONFIG";
#endif
else if (_hRootKey == HKEY_CURRENT_USER)
result = "HKEY_CURRENT_USER";
else if (_hRootKey == HKEY_LOCAL_MACHINE)
result = "HKEY_LOCAL_MACHINE";
else if (_hRootKey == HKEY_USERS)
result = "HKEY_USERS";
#if defined(HKEY_PERFORMANCE_DATA)
else if (_hRootKey == HKEY_PERFORMANCE_DATA)
result = "HKEY_PERFORMANCE_DATA";
#endif
else
result = "(UNKNOWN)";
result += '\\';
result += _subKey;
return result;
}
std::string WinRegistryKey::key(const std::string& valueName) const
{
std::string result = key();
if (!valueName.empty())
{
result += '\\';
result += valueName;
}
return result;
}
HKEY WinRegistryKey::handle()
{
open();
return _hKey;
}
HKEY WinRegistryKey::handleFor(const std::string& rootKey)
{
if (rootKey == "HKEY_CLASSES_ROOT")
return HKEY_CLASSES_ROOT;
#if defined(HKEY_CURRENT_CONFIG)
else if (rootKey == "HKEY_CURRENT_CONFIG")
return HKEY_CURRENT_CONFIG;
#endif
else if (rootKey == "HKEY_CURRENT_USER")
return HKEY_CURRENT_USER;
else if (rootKey == "HKEY_LOCAL_MACHINE")
return HKEY_LOCAL_MACHINE;
else if (rootKey == "HKEY_USERS")
return HKEY_USERS;
#if defined(HKEY_PERFORMANCE_DATA)
else if (rootKey == "HKEY_PERFORMANCE_DATA")
return HKEY_PERFORMANCE_DATA;
#endif
else
throw InvalidArgumentException("Not a valid root key", rootKey);
}
void WinRegistryKey::handleSetError(const std::string& name)
{
std::string msg = "Failed to set registry value";
throw SystemException(msg, key(name));
}
void WinRegistryKey::subKeys(WinRegistryKey::Keys& keys)
{
open();
DWORD subKeyCount = 0;
DWORD valueCount = 0;
if (RegQueryInfoKey(_hKey, NULL, NULL, NULL, &subKeyCount, NULL, NULL, &valueCount, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
return;
wchar_t buf[256];
DWORD bufSize = sizeof(buf)/sizeof(wchar_t);
for (DWORD i = 0; i< subKeyCount; ++i)
{
if (RegEnumKeyExW(_hKey, i, buf, &bufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
std::wstring uname(buf);
std::string name;
Poco::UnicodeConverter::toUTF8(uname, name);
keys.push_back(name);
}
bufSize = sizeof(buf)/sizeof(wchar_t);
}
}
void WinRegistryKey::values(WinRegistryKey::Values& vals)
{
open();
DWORD valueCount = 0;
if (RegQueryInfoKey(_hKey, NULL, NULL, NULL, NULL, NULL, NULL, &valueCount, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
return ;
wchar_t buf[256];
DWORD bufSize = sizeof(buf)/sizeof(wchar_t);
for (DWORD i = 0; i< valueCount; ++i)
{
if (RegEnumValueW(_hKey, i, buf, &bufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
std::wstring uname(buf);
std::string name;
Poco::UnicodeConverter::toUTF8(uname, name);
vals.push_back(name);
}
bufSize = sizeof(buf)/sizeof(wchar_t);
}
}
} } // namespace Poco::Util