blob: 48ab3125bd092b2f1d24b4e47a6c15613990a63d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
//---------------------------------------
//
//---------------------------------------
#ifdef _MSC_VER
#pragma warning(push, 1) /* disable warnings within system headers */
#endif
#include <windows.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <malloc.h>
#include "registrywnt.hxx"
#include "registryvalueimpl.hxx"
#include "registryexception.hxx"
#include <assert.h>
#ifdef _MSC_VER
#pragma warning(disable : 4786 4350)
#endif
//---------------------------------------
//
//---------------------------------------
const size_t MAX_TMP_BUFF_SIZE = 1024 * sizeof(wchar_t);
//############################################
// Creation
// only possible through WindowsRegistry class
//############################################
//-----------------------------------------------------
/** Create instance and open the specified Registry key
*/
RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey, const std::wstring& KeyName) :
RegistryKeyImpl(RootKey, KeyName)
{
}
//-----------------------------------------------------
/** Create instance and open the specified Registry key
*/
RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey) :
RegistryKeyImpl(RootKey)
{
}
//-----------------------------------------------------
/** Create an instances of the specified Registry key,
the key is assumed to be already opened.
*/
RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
RegistryKeyImpl(RootKey, SubKey, KeyName, Writeable)
{
}
//############################################
// Queries
//############################################
//-----------------------------------------------------
/** The number of sub values of the key at hand
@precond IsOpen = true
@throws
*/
size_t RegistryKeyImplWinNT::GetSubValueCount() const
{
assert(IsOpen());
DWORD nSubValues = 0;
LONG rc = RegQueryInfoKeyW(
m_hSubKey,
0, 0, 0, 0, 0, 0, &nSubValues, 0, 0, 0, 0);
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
return nSubValues;
}
//-----------------------------------------------------
/** The number of sub-keys of the key at hand
@precond IsOpen = true
@throws
*/
size_t RegistryKeyImplWinNT::GetSubKeyCount() const
{
assert(IsOpen());
DWORD nSubKeys = 0;
LONG rc = RegQueryInfoKeyA(
m_hSubKey,
0, 0, 0, &nSubKeys, 0, 0, 0, 0, 0, 0, 0);
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
return nSubKeys;
}
//-----------------------------------------------------
/**
*/
StringListPtr RegistryKeyImplWinNT::GetSubKeyNames() const
{
assert(IsOpen());
wchar_t buff[1024];
DWORD buff_size = sizeof(buff);
FILETIME ftime;
StringList* key_names = new StringList();
LONG rc = ERROR_SUCCESS;
for (DWORD i = 0; /* left empty */; i++)
{
rc = RegEnumKeyExW(
m_hSubKey, i, buff, &buff_size,
0, 0, 0, &ftime);
if (ERROR_SUCCESS != rc &&
ERROR_MORE_DATA != rc)
break;
buff_size = sizeof(buff);
key_names->push_back(buff);
}
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc)
throw RegistryException(rc);
#if (_MSC_VER < 1300) && !defined(__MINGW32__)
return key_names;
#else
return (StringListPtr) key_names;
#endif
}
//-----------------------------------------------------
/**
*/
StringListPtr RegistryKeyImplWinNT::GetSubValueNames() const
{
assert(IsOpen());
wchar_t buff[1024];
DWORD buff_size = sizeof(buff);
StringList* value_names = new StringList();
LONG rc = ERROR_SUCCESS;
for (DWORD i = 0; /* left empty */; i++)
{
rc = RegEnumValueW(
m_hSubKey, i, buff, &buff_size,
0, 0, 0, 0);
if (ERROR_SUCCESS != rc &&
ERROR_MORE_DATA != rc)
break;
buff_size = sizeof(buff);
value_names->push_back(buff);
}
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc)
throw RegistryException(rc);
#if (_MSC_VER < 1300) && !defined(__MINGW32__)
return value_names;
#else
return (StringListPtr) value_names;
#endif
}
//-----------------------------------------------------
/** Get the specified registry value
@precond IsOpen = true
*/
RegistryValue RegistryKeyImplWinNT::GetValue(const std::wstring& Name) const
{
assert(IsOpen());
DWORD Type;
wchar_t buff[MAX_TMP_BUFF_SIZE];
DWORD size = sizeof(buff);
LONG rc = RegQueryValueExW(
m_hSubKey,
Name.c_str(),
0,
&Type,
reinterpret_cast<LPBYTE>(buff),
&size);
if (ERROR_FILE_NOT_FOUND == rc)
throw RegistryValueNotFoundException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
RegistryValue regval;
if (REG_DWORD == Type)
{
regval = RegistryValue(new RegistryValueImpl(Name, *(reinterpret_cast<int*>(buff))));
}
else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type)
{
if (size > 0)
regval = RegistryValue(new RegistryValueImpl(Name, std::wstring(reinterpret_cast<wchar_t*>(buff))));
else
regval = RegistryValue(new RegistryValueImpl(Name, std::wstring()));
}
else
{
assert(false);
}
return regval;
}
//-----------------------------------------------------
/** Get the specified registry value, return the given
default value if value not found
@precond IsOpen = true
*/
RegistryValue RegistryKeyImplWinNT::GetValue(const std::wstring& Name, const RegistryValue& Default) const
{
assert(IsOpen());
DWORD Type;
wchar_t buff[MAX_TMP_BUFF_SIZE];
DWORD size = sizeof(buff);
LONG rc = RegQueryValueExW(
m_hSubKey,
Name.c_str(),
0,
&Type,
reinterpret_cast<LPBYTE>(buff),
&size);
if (ERROR_FILE_NOT_FOUND == rc)
{
#if (_MSC_VER < 1300) && !defined(__MINGW32__)
return Default;
#else
RegistryValue regval_ptr;
regval_ptr = RegistryValue(new RegistryValueImpl(*Default));
return regval_ptr;
#endif
}
if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
RegistryValue regval;
if (REG_DWORD == Type)
regval = RegistryValue(new RegistryValueImpl(Name, *reinterpret_cast<int*>(buff)));
else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type)
regval = RegistryValue(new RegistryValueImpl(Name, std::wstring(reinterpret_cast<wchar_t*>(buff))));
else
assert(false);
return regval;
}
//############################################
// Commands
//############################################
//-----------------------------------------------------
/** Open the registry key, has no effect if
the key is already open
@precond IsOpen = false
@throws RegistryKeyNotFoundException
RegistryWriteAccessDenyException
RegistryAccessDenyException
*/
void RegistryKeyImplWinNT::Open(bool Writeable)
{
assert(!IsOpen());
REGSAM regsam = KEY_READ;
if (Writeable)
regsam |= KEY_WRITE;
LONG rc = RegOpenKeyExW(
m_hRootKey,
m_KeyName.c_str(),
0,
regsam,
&m_hSubKey);
if (ERROR_FILE_NOT_FOUND == rc)
throw RegistryKeyNotFoundException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
m_IsWriteable = Writeable;
assert(IsOpen());
}
//-----------------------------------------------------
/** Open the specified sub-key of the registry key
at hand
@precond IsOpen = true
HasSubKey(Name) = true
@throws RegistryIOException
RegistryKeyNotFoundException
RegistryAccessDeniedException
*/
RegistryKey RegistryKeyImplWinNT::OpenSubKey(const std::wstring& Name, bool Writeable)
{
RegistryKey regkey(new RegistryKeyImplWinNT(m_hSubKey, Name));
regkey->Open(Writeable);
return regkey;
}
//-----------------------------------------------------
/** Creates a new sub-key below the key at hand
@precond IsOpen = true
IsWriteable = true
@throws RegistryIOException
RegistryWriteAccessDenyException
*/
RegistryKey RegistryKeyImplWinNT::CreateSubKey(const std::wstring& Name)
{
assert(IsOpen());
assert(IsWriteable());
HKEY hRoot = IsRootKey() ? m_hRootKey : m_hSubKey;
HKEY hKey;
LONG rc = RegCreateKeyExW(
hRoot,
Name.c_str(),
0,
0,
REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE,
0,
&hKey,
0);
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
return RegistryKey(new RegistryKeyImplWinNT(hRoot, hKey, Name));
}
//-----------------------------------------------------
/** Deletes a sub-key below the key at hand, the
key must not have sub-keys
@precond IsOpen = true
IsWriteable = true
@throws RegistryIOException
RegistryWriteAccessDenyException
*/
void RegistryKeyImplWinNT::DeleteSubKey(const std::wstring& Name)
{
assert(IsOpen());
assert(IsWriteable());
assert(HasSubKey(Name));
RegistryKey SubKey = OpenSubKey(Name);
size_t nSubKeyCount = SubKey->GetSubKeyCount();
assert(0 == nSubKeyCount);
if (nSubKeyCount)
throw RegistryInvalidOperationException(ERROR_NOT_SUPPORTED);
LONG rc = RegDeleteKeyW(m_hSubKey, Name.c_str());
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
}
//-----------------------------------------------------
/** Deletes a sub-key below the key at hand with all
its sub-keys
@precond IsOpen = true
IsWriteable = true;
@throws RegistryIOException
RegistryWriteAccessDenyException
*/
void RegistryKeyImplWinNT::DeleteSubKeyTree(const std::wstring& Name)
{
ImplDeleteSubKeyTree(m_hSubKey, Name);
}
//-----------------------------------------------------
/** Deletes a sub-key below the key at hand with all
its sub-keys
@precond IsOpen = true
IsWriteable = true;
@throws RegistryIOException
RegistryWriteAccessDenyException
*/
LONG RegistryKeyImplWinNT::ImplDeleteSubKeyTree(HKEY RootKey, const std::wstring& Name)
{
assert(IsOpen());
HKEY hKey;
LONG rc = RegOpenKeyExW(
RootKey,
Name.c_str(),
0,
KEY_READ | DELETE,
&hKey);
if (ERROR_SUCCESS == rc)
{
wchar_t* lpSubKey;
DWORD nMaxSubKeyLen;
rc = RegQueryInfoKeyW(
hKey, 0, 0, 0, 0,
&nMaxSubKeyLen,
0, 0, 0, 0, 0, 0);
nMaxSubKeyLen++; // space for trailing '\0'
lpSubKey = reinterpret_cast<wchar_t*>(
_alloca(nMaxSubKeyLen*sizeof(wchar_t)));
while (ERROR_SUCCESS == rc)
{
DWORD nLen = nMaxSubKeyLen;
rc = RegEnumKeyExW(
hKey,
0, // always index zero
lpSubKey,
&nLen,
0, 0, 0, 0);
if (ERROR_NO_MORE_ITEMS == rc)
{
rc = RegDeleteKeyW(RootKey, Name.c_str());
break;
}
else if (rc == ERROR_SUCCESS)
{
rc = ImplDeleteSubKeyTree(hKey, lpSubKey);
}
} // while
RegCloseKey(hKey);
} // if
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_FILE_NOT_FOUND == rc)
throw RegistryKeyNotFoundException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
return rc;
}
//-----------------------------------------------------
/** Delete the specified value
@precond IsOpen = true
IsWriteable = true
HasValue(Name) = true
@throws RegistryIOException
RegistryWriteAccessDeniedException
RegistryValueNotFoundException
*/
void RegistryKeyImplWinNT::DeleteValue(const std::wstring& Name)
{
assert(IsOpen());
assert(HasValue(Name));
assert(IsWriteable());
LONG rc = RegDeleteValueW(
m_hSubKey,
Name.c_str());
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryNoWriteAccessException(rc);
else if (ERROR_FILE_NOT_FOUND == rc)
throw RegistryValueNotFoundException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
}
//-----------------------------------------------------
/** Set the specified registry value
@precond IsOpen = true
IsWriteable = true
@throws RegistryIOException
RegistryWriteAccessDenyException
*/
void RegistryKeyImplWinNT::SetValue(const RegistryValue& Value)
{
assert(IsOpen());
assert(IsWriteable());
LONG rc = RegSetValueExW(
m_hSubKey,
Value->GetName().c_str(),
0,
Value->GetType(),
reinterpret_cast<const unsigned char*>(Value->GetDataBuffer()),
static_cast<DWORD>(Value->GetDataSize()));
if (ERROR_INVALID_HANDLE == rc)
throw RegistryIOException(rc);
else if (ERROR_ACCESS_DENIED == rc)
throw RegistryAccessDeniedException(rc);
else if (ERROR_SUCCESS != rc)
throw RegistryException(rc);
}