REGISTRY()
{
/*HKEY*/m_pRoot = nullptr;
/*HKEY*/m_pReturnKey = nullptr;
m_pPath = nullptr;
m_pValueName = nullptr;
}
~REGISTRY()
{
if ( m_pReturnKey )
{
RegCloseKey(m_pReturnKey);
m_pReturnKey = nullptr;
}
if ( m_pRoot )
{
RegCloseKey(m_pRoot);
m_pRoot = nullptr;
}
}
I have a class which handles All Registry functions of my applications, I let the Object's Destructor handle the closing of the HKEY
s (as Shown Above). I have adopted the answer provided here, but instead of using HANDLES
I've simply Set the HKEY
s as nullptr
during the object's construction and check if it's not nullptr
during destruction and close it. I'm also using Smart Pointers<unique_ptr
> when using it to ensure that the Destructor get's called even when it throws an exception.
Since Upon Checking ,when RegOpenKeyExA
,RegCreateKeyExA
, RegSetValueEx
, or RegQueryValueExA
returns anything other than ERROR_SUCCESS
it doesn't do anything to the passed HKEY
and it remained as a nullptr
.
Aside from this method is there a proper way to check if a HKEY/PHKEY is active and valid? Scouring the MSDN page on winreg.h provided me nothing, if it's there I might be blind or it's not using a Function Name that is not obvious to an amateur like me.
The winreg API doesn't set aside a value that represents an invalid HKEY
(unlike, say, the fileapi, where CreateFileW
uses INVALID_HANDLE_VALUE
for this purpose). Instead, API calls report whether they succeeded, and only then guarantee to have written an HKEY
to the location provided by the caller.
If your implementation needs to know whether any given piece of information represents valid data, you'll have to record this information separately. Starting with C++17, std::optional
is the standard tool for this purpose.
A possible solution to your problem could thus be:
class REGISTRY
{
std::optional<HKEY> m_pRoot;
std::optional<HKEY> m_pReturnKey;
// ...
}
REGISTRY::~REGISTRY()
{
if (m_pReturnKey)
// equivalent to
// if (m_pReturnKey.has_value())
{
RegCloseKey(m_pReturnKey.value());
m_pReturnKey = {};
}
// ...
}
m_pRoot
and m_pReturnKey
are default-initialized, meaning, they hold a value of type std::nullopt_t
. The d'tor will observe this, and not do anything. Which solves the problem as stated.