-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OrcLib: add Registry class to read values from the registry
- Loading branch information
1 parent
cdcc0ea
commit 68eab1e
Showing
5 changed files
with
485 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,312 @@ | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
// | ||
// Copyright © 2011-2019 ANSSI. All Rights Reserved. | ||
// | ||
// Author(s): Jean Gautier (ANSSI) | ||
// | ||
|
||
#include "stdafx.h" | ||
|
||
#include "Registry.h" | ||
|
||
|
||
template <> | ||
Orc::Result<ULONG32> | ||
Orc::Registry::Read<ULONG32>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) | ||
{ | ||
HKEY hKey = nullptr; | ||
|
||
if (szKeyName) | ||
{ | ||
if (auto status = RegOpenKeyExW(hParentKey, szKeyName, REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, &hKey); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to registry key %s\r\n", szKeyName); | ||
return Orc::Result<ULONG32>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
hKey = hParentKey; | ||
} | ||
|
||
BOOST_SCOPE_EXIT(&hKey, &hParentKey) | ||
{ | ||
if (hKey != hParentKey) | ||
RegCloseKey(hKey); | ||
} | ||
BOOST_SCOPE_EXIT_END; | ||
|
||
Buffer<ULONG32, 1> valueBuffer; | ||
DWORD cbBytes = sizeof(ULONG32); | ||
valueBuffer.reserve(1); | ||
DWORD dwValueType = 0; | ||
|
||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, &dwValueType, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
if (status == ERROR_MORE_DATA) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Unexepected registry value \"%s\" is bigger than expected (ULONG32)\r\n", szValueName); | ||
return Orc::Result<ULONG32>(HRESULT_FROM_WIN32(status)); | ||
} | ||
else | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to open registry \"%s\" value\r\n", szValueName); | ||
return Orc::Result<ULONG32>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
valueBuffer.use((cbBytes / sizeof(ULONG32))); | ||
} | ||
if (dwValueType != REG_DWORD || (dwValueType != REG_BINARY && cbBytes!=sizeof(ULONG32))) | ||
{ | ||
log::Error( | ||
pLog, | ||
HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH), | ||
L"Unexpected value \"%s\" type (not ULONG32 compatible)\r\n", | ||
szValueName); | ||
return Orc::Result<ULONG32>(HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)); | ||
} | ||
|
||
return Result<ULONG32>(valueBuffer[0]); | ||
} | ||
|
||
template <> | ||
Orc::Result<ULONG64> | ||
Orc::Registry::Read<ULONG64>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) | ||
{ | ||
HKEY hKey = nullptr; | ||
|
||
if (szKeyName) | ||
{ | ||
if (auto status = RegOpenKeyExW(hParentKey, szKeyName, REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, &hKey); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to registry key %s\r\n", szKeyName); | ||
return Orc::Result<ULONG64>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
hKey = hParentKey; | ||
} | ||
|
||
BOOST_SCOPE_EXIT(&hKey, &hParentKey) | ||
{ | ||
if (hKey != hParentKey) | ||
RegCloseKey(hKey); | ||
} | ||
BOOST_SCOPE_EXIT_END; | ||
|
||
Buffer<ULONG64, 1> valueBuffer; | ||
DWORD cbBytes = sizeof(ULONG64); | ||
valueBuffer.reserve(1); | ||
DWORD dwValueType = 0; | ||
|
||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, &dwValueType, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
if (status == ERROR_MORE_DATA) | ||
{ | ||
log::Error( | ||
pLog, | ||
HRESULT_FROM_WIN32(status), | ||
L"Unexepected registry value \"%s\" is bigger than expected (ULONG32)\r\n", | ||
szValueName); | ||
return Orc::Result<ULONG64>(HRESULT_FROM_WIN32(status)); | ||
} | ||
else | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to open registry \"%s\" value\r\n", szValueName); | ||
return Orc::Result<ULONG64>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
valueBuffer.use((cbBytes / sizeof(ULONG64))); | ||
} | ||
if (dwValueType != REG_QWORD || (dwValueType != REG_BINARY && cbBytes != sizeof(ULONG64))) | ||
{ | ||
log::Error( | ||
pLog, | ||
HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH), | ||
L"Unexpected value \"%s\" type (not ULONG32 compatible)\r\n", | ||
szValueName); | ||
return Orc::Result<ULONG64>(HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)); | ||
} | ||
|
||
return Result<ULONG64>(valueBuffer[0]); | ||
} | ||
|
||
template <> | ||
Orc::Result<Orc::ByteBuffer> | ||
Orc::Registry::Read<Orc::ByteBuffer>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) | ||
{ | ||
HKEY hKey = nullptr; | ||
|
||
if (szKeyName) | ||
{ | ||
if (auto status = RegOpenKeyExW(hParentKey, szKeyName, REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, &hKey); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to registry key %s\r\n", szKeyName); | ||
return Orc::Result<ByteBuffer>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
hKey = hParentKey; | ||
} | ||
|
||
BOOST_SCOPE_EXIT(&hKey, &hParentKey) | ||
{ | ||
if (hKey != hParentKey) | ||
RegCloseKey(hKey); | ||
} | ||
BOOST_SCOPE_EXIT_END; | ||
|
||
ByteBuffer valueBuffer; | ||
DWORD cbBytes = valueBuffer.inner_elts() * sizeof(BYTE); | ||
valueBuffer.reserve(valueBuffer.inner_elts()); | ||
DWORD dwValueType = 0; | ||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, &dwValueType, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
if (status == ERROR_MORE_DATA) | ||
{ | ||
valueBuffer.resize(cbBytes / sizeof(BYTE)); | ||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, NULL, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to reg value \"%s:%s\" value\r\n", szKeyName?szKeyName:L"", szValueName); | ||
return Orc::Result<ByteBuffer>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
log::Error( | ||
pLog, HRESULT_FROM_WIN32(status), L"Failed to reg value \"%s:%s\" value\r\n", szKeyName?szKeyName:L"", szValueName); | ||
return Orc::Result<ByteBuffer>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
valueBuffer.use((cbBytes / sizeof(BYTE))); | ||
} | ||
return Orc::Result<ByteBuffer>(std::move(valueBuffer)); | ||
} | ||
|
||
template <> | ||
Orc::Result<std::wstring> | ||
Orc::Registry::Read<std::wstring>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) | ||
{ | ||
HKEY hKey = nullptr; | ||
|
||
if (szKeyName) | ||
{ | ||
if (auto status = RegOpenKeyExW(hParentKey, szKeyName, REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, &hKey); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to registry key %s\r\n", szKeyName); | ||
return Orc::Result<std::wstring>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
hKey = hParentKey; | ||
} | ||
|
||
BOOST_SCOPE_EXIT(&hKey, &hParentKey) | ||
{ | ||
if (hKey != hParentKey) | ||
RegCloseKey(hKey); | ||
} | ||
BOOST_SCOPE_EXIT_END; | ||
|
||
Buffer<WCHAR, MAX_PATH> valueBuffer; | ||
DWORD cbBytes = MAX_PATH * sizeof(WCHAR); | ||
valueBuffer.reserve(MAX_PATH); | ||
DWORD dwValueType = 0; | ||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, &dwValueType, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
if (status == ERROR_MORE_DATA) | ||
{ | ||
valueBuffer.resize(cbBytes / sizeof(WCHAR)); | ||
if (auto status = RegQueryValueExW(hKey, szValueName, NULL, NULL, (LPBYTE)valueBuffer.get(), &cbBytes); | ||
status != ERROR_SUCCESS) | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to reg value \"%s\" value\r\n", szValueName); | ||
return Orc::Result<std::wstring>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
log::Error(pLog, HRESULT_FROM_WIN32(status), L"Failed to open profile list \"%s\" value\r\n", szValueName); | ||
return Orc::Result<std::wstring>(HRESULT_FROM_WIN32(status)); | ||
} | ||
} | ||
else | ||
{ | ||
valueBuffer.use((cbBytes / sizeof(WCHAR))); | ||
} | ||
|
||
if (dwValueType == REG_SZ) | ||
{ | ||
if (valueBuffer.size() | ||
>= 1) // If string is not empty, we need to get rid of the trailing \0 to build a wstring | ||
{ | ||
valueBuffer.resize(valueBuffer.size() - 1); | ||
} | ||
|
||
return Orc::Result<std::wstring>(std::wstring(valueBuffer.get(), valueBuffer.size())); | ||
} | ||
else if (dwValueType == REG_EXPAND_SZ) | ||
{ | ||
Buffer<WCHAR, MAX_PATH> expandBuffer; | ||
expandBuffer.reserve(MAX_PATH); | ||
|
||
if (auto cbSize = ExpandEnvironmentStringsW(valueBuffer.get(), expandBuffer.get(), MAX_PATH); cbSize > MAX_PATH) | ||
{ | ||
expandBuffer.reserve(cbSize); | ||
if (auto cbSizeReTry = ExpandEnvironmentStringsW(valueBuffer.get(), expandBuffer.get(), cbSize); | ||
cbSizeReTry == cbSize) | ||
{ | ||
expandBuffer.use(cbSize); | ||
} | ||
else | ||
{ | ||
throw Exception( | ||
ExceptionSeverity::Continue, E_FAIL, L"Unexpected return value for ExpandEnvironmentStringsW\r\n"); | ||
} | ||
} | ||
else | ||
{ | ||
expandBuffer.use(cbSize); | ||
} | ||
return Orc::Result<std::wstring>(std::wstring(expandBuffer.get(), expandBuffer.size())); | ||
} | ||
else | ||
{ | ||
log::Error( | ||
pLog, | ||
HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH), | ||
L"Registry value %s is not of the expected (REG_*SZ) type\r\n", | ||
szValueName); | ||
return Orc::Result<std::wstring>(HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)); | ||
} | ||
} | ||
|
||
template <> | ||
Orc::Result<std::filesystem::path> | ||
Orc::Registry::Read<std::filesystem::path>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) | ||
{ | ||
auto string = Read<std::wstring>(pLog, hParentKey, szKeyName, szValueName); | ||
if (string.is_ok()) | ||
return string.unwrap(); | ||
else | ||
return string.err(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
// | ||
// Copyright © 2011-2019 ANSSI. All Rights Reserved. | ||
// | ||
// Author(s): Jean Gautier (ANSSI) | ||
// | ||
#pragma once | ||
|
||
#include "OrcLib.h" | ||
|
||
#include "OrcResult.h" | ||
#include "Buffer.h" | ||
|
||
#include <optional> | ||
#include <filesystem> | ||
#include <Windows.h> | ||
#include "boost/scope_exit.hpp" | ||
|
||
#pragma managed(push, off) | ||
|
||
|
||
namespace Orc { | ||
|
||
class LogFileWriter; | ||
|
||
class ORCLIB_API Registry | ||
{ | ||
public: | ||
template <typename _T> | ||
static Result<_T> Read(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName) { | ||
static_assert(false, "Registry read for your type must be a specialised version"); | ||
} | ||
}; | ||
|
||
|
||
template <> | ||
Orc::Result<ULONG32> | ||
Orc::Registry::Read<ULONG32>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
template <> | ||
Orc::Result<ULONG64> | ||
Orc::Registry::Read<ULONG64>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
template <> | ||
Orc::Result<ByteBuffer> | ||
Orc::Registry::Read<ByteBuffer>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
template <> | ||
Orc::Result<std::wstring> | ||
Orc::Registry::Read<std::wstring>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
template <> | ||
Orc::Result<std::vector<std::wstring>> | ||
Orc::Registry::Read<std::vector<std::wstring>>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
template <> | ||
Orc::Result<std::filesystem::path> | ||
Orc::Registry::Read<std::filesystem::path>(const logger& pLog, HKEY hParentKey, LPWSTR szKeyName, LPWSTR szValueName); | ||
|
||
} // namespace Orc | ||
|
||
|
||
#pragma managed(pop) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.