#include "wx/string.h"
#include "wx/intl.h"
#include "wx/log.h"
-#include "wx/config.h" // for wxExpandEnvVars
#ifndef __WIN16__
#include <stdlib.h> // for _MAX_PATH
#ifndef _MAX_PATH
- #define _MAX_PATH 512
+ #define _MAX_PATH 512
#endif
// our header
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
-// @ const_cast<> is not yet supported by all compilers
+
+// const_cast<> is not yet supported by all compilers
#define CONST_CAST ((wxRegKey *)this)->
-#if !USE_MUTABLE
- #define m_dwLastError CONST_CAST m_dwLastError
-#endif
+// and neither is mutable which m_dwLastError should be
+#define m_dwLastError CONST_CAST m_dwLastError
// ----------------------------------------------------------------------------
// non member functions
wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey)
{
- wxString strRoot = strKey.Left(REG_SEPARATOR);
+ wxString strRoot = strKey.BeforeFirst(REG_SEPARATOR);
HKEY hRootKey = 0;
size_t ui;
wxRegKey::wxRegKey()
{
- m_hKey = 0;
m_hRootKey = (WXHKEY) aStdKeys[HKCR].hkey;
- m_dwLastError = 0;
+
+ Init();
}
wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey)
{
m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey;
- m_hKey = (WXHKEY) NULL;
- m_dwLastError = 0;
+
+ Init();
}
// parent is a predefined (and preopened) key
{
RemoveTrailingSeparator(m_strKey);
m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey;
- m_hKey = (WXHKEY) NULL;
- m_dwLastError = 0;
+
+ Init();
}
// parent is a normal regkey
RemoveTrailingSeparator(m_strKey);
m_hRootKey = keyParent.m_hRootKey;
- m_hKey = (WXHKEY) NULL;
- m_dwLastError = 0;
+
+ Init();
}
// dtor closes the key releasing system resource
Close();
// combine our name with parent's to get the full name
- m_strKey = keyParent.m_strKey;
+
+ // NB: this method is called by wxRegConfig::SetPath() which is a performance
+ // critical function and so it preallocates space for our m_strKey to
+ // gain some speed - this is why we only use += here and not = which
+ // would just free the prealloc'd buffer and would have to realloc it the
+ // next line!
+ m_strKey.clear();
+ m_strKey += keyParent.m_strKey;
if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
m_strKey += REG_SEPARATOR;
m_strKey += strKey;
#if defined(__WIN32__) && !defined(__TWIN32__)
// old gcc headers incorrectly prototype RegQueryInfoKey()
-#ifdef __GNUWIN32_OLD__
+#if defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__)
#define REG_PARAM (size_t *)
#else
#define REG_PARAM (LPDWORD)
#endif
+ // it might be unexpected to some that this function doesn't open the key
+ wxASSERT_MSG( IsOpened(), _T("key should be opened in GetKeyInfo") );
+
m_dwLastError = ::RegQueryInfoKey
(
(HKEY) m_hKey,
GetName().c_str());
return FALSE;
}
- else
- return TRUE;
+
+ return TRUE;
#else // Win16
wxFAIL_MSG("GetKeyInfo() not implemented");
{
if ( IsOpened() ) {
m_dwLastError = RegCloseKey((HKEY) m_hKey);
+ m_hKey = 0;
+
if ( m_dwLastError != ERROR_SUCCESS ) {
wxLogSysError(m_dwLastError, _("Can't close registry key '%s'"),
GetName().c_str());
- m_hKey = 0;
return FALSE;
}
- else {
- m_hKey = 0;
- }
}
return TRUE;
ok = FALSE;
}
- if ( !ok || !CopyValue(szValueOld, *this, szValueNew) ) {
+ if ( !ok ||
+ !CopyValue(szValueOld, *this, szValueNew) ||
+ !DeleteValue(szValueOld) ) {
wxLogError(_("Failed to rename registry value '%s' to '%s'."),
szValueOld, szValueNew);
wxRegKey& keyDst,
const wxChar *szValueNew)
{
+ if ( !szValueNew ) {
+ // by default, use the same name
+ szValueNew = szValue;
+ }
+
switch ( GetValueType(szValue) ) {
case Type_String:
{
}
}
-bool wxRegKey::Copy(const wxString& strNewName)
+bool wxRegKey::Rename(const wxChar *szNewName)
+{
+ wxCHECK_MSG( !!m_strKey, FALSE, _T("registry hives can't be renamed") );
+
+ if ( !Exists() ) {
+ wxLogError(_("Registry key '%s' does not exist, cannot rename it."),
+ GetFullName(this));
+
+ return FALSE;
+ }
+
+ // do we stay in the same hive?
+ bool inSameHive = !wxStrchr(szNewName, REG_SEPARATOR);
+
+ // construct the full new name of the key
+ wxRegKey keyDst;
+
+ if ( inSameHive ) {
+ // rename the key to the new name under the same parent
+ wxString strKey = m_strKey.BeforeLast(REG_SEPARATOR);
+ if ( !!strKey ) {
+ // don't add '\\' in the start if strFullNewName is empty
+ strKey += REG_SEPARATOR;
+ }
+
+ strKey += szNewName;
+
+ keyDst.SetName(GetStdKeyFromHkey(m_hRootKey), strKey);
+ }
+ else {
+ // this is the full name already
+ keyDst.SetName(szNewName);
+ }
+
+ bool ok = keyDst.Create(FALSE /* fail if alredy exists */);
+ if ( !ok ) {
+ wxLogError(_("Registry key '%s' already exists."),
+ GetFullName(&keyDst));
+ }
+ else {
+ ok = Copy(keyDst) && DeleteSelf();
+ }
+
+ if ( !ok ) {
+ wxLogError(_("Failed to rename the registry key '%s' to '%s'."),
+ GetFullName(this), GetFullName(&keyDst));
+ }
+ else {
+ m_hRootKey = keyDst.m_hRootKey;
+ m_strKey = keyDst.m_strKey;
+ }
+
+ return ok;
+}
+
+bool wxRegKey::Copy(const wxChar *szNewName)
{
// create the new key first
- wxRegKey keyDst(strNewName);
+ wxRegKey keyDst(szNewName);
bool ok = keyDst.Create(FALSE /* fail if alredy exists */);
if ( ok ) {
ok = Copy(keyDst);
wxRegKey key(*this, strKey);
wxString keyName;
keyName << GetFullName(&keyDst) << REG_SEPARATOR << strKey;
- ok = key.Copy(keyName);
+ ok = key.Copy((const wxChar*) keyName);
if ( ok )
bCont = GetNextKey(strKey, lIndex);
}
if ( !ok ) {
- wxLogError(_("Failed to copy the contents of registry key '%s' to "
- "'%s'."), GetFullName(this), GetFullName(&keyDst));
+ wxLogError(_("Failed to copy the contents of registry key '%s' to '%s'."), GetFullName(this), GetFullName(&keyDst));
}
return ok;
// prevent a buggy program from erasing one of the root registry keys or an
// immediate subkey (i.e. one which doesn't have '\\' inside) of any other
// key except HKCR (HKCR has some "deleteable" subkeys)
- if ( m_strKey.IsEmpty() || (m_hRootKey != HKCR &&
- m_strKey.Find(REG_SEPARATOR) == wxNOT_FOUND) ) {
- wxLogError(_("Registry key '%s' is needed for normal system operation,\n"
- "deleting it will leave your system in unusable state:\n"
- "operation aborted."), GetFullName(this));
+ if ( m_strKey.IsEmpty() ||
+ ((m_hRootKey != (WXHKEY) aStdKeys[HKCR].hkey) &&
+ (m_strKey.Find(REG_SEPARATOR) == wxNOT_FOUND)) ) {
+ wxLogError(_("Registry key '%s' is needed for normal system operation,\ndeleting it will leave your system in unusable state:\noperation aborted."), GetFullName(this));
return FALSE;
}
wxLogNull nolog;
#ifdef __WIN32__
- if ( CONST_CAST Open() ) {
- return RegQueryValueEx((HKEY) m_hKey, WXSTRINGCAST szValue, RESERVED,
- NULL, NULL, NULL) == ERROR_SUCCESS;
- }
- else
- return FALSE;
+ if ( !CONST_CAST Open() )
+ return FALSE;
+
+ LONG dwRet = ::RegQueryValueEx((HKEY) m_hKey,
+ WXSTRINGCAST szValue,
+ RESERVED,
+ NULL, NULL, NULL);
+ return dwRet == ERROR_SUCCESS;
#else // WIN16
// only unnamed value exists
return IsEmpty(szValue);
// this function should be silent, so suppress possible messages from Open()
wxLogNull nolog;
- if ( CONST_CAST Open() )
- return KeyExists(m_hKey, szKey);
- else
+ if ( !CONST_CAST Open() )
return FALSE;
+
+ return KeyExists(m_hKey, szKey);
}
wxRegKey::ValueType wxRegKey::GetValueType(const wxChar *szValue) const
#endif //Win32
-bool wxRegKey::QueryValue(const wxChar *szValue, wxString& strValue) const
+bool wxRegKey::QueryValue(const wxChar *szValue,
+ wxString& strValue,
+ bool raw) const
{
if ( CONST_CAST Open() ) {
#ifdef __WIN32__
pBuf,
&dwSize);
strValue.UngetWriteBuf();
+
+ // expand the var expansions in the string unless disabled
+ if ( (dwType == REG_EXPAND_SZ) && !raw )
+ {
+ DWORD dwExpSize = ::ExpandEnvironmentStrings(strValue, NULL, 0);
+ bool ok = dwExpSize != 0;
+ if ( ok )
+ {
+ wxString strExpValue;
+ ok = ::ExpandEnvironmentStrings
+ (
+ strValue,
+ strExpValue.GetWriteBuf(dwExpSize),
+ dwExpSize
+ ) != 0;
+ strExpValue.UngetWriteBuf();
+ strValue = strExpValue;
+ }
+
+ if ( !ok )
+ {
+ wxLogLastError(_T("ExpandEnvironmentStrings"));
+ }
+ }
}
if ( m_dwLastError == ERROR_SUCCESS ) {
#if defined( __WIN32__) && !defined(__TWIN32__)
m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, (DWORD) RESERVED, REG_SZ,
(RegString)strValue.c_str(),
- strValue.Len() + 1);
+ (strValue.Len() + 1)*sizeof(wxChar));
if ( m_dwLastError == ERROR_SUCCESS )
return TRUE;
#else //WIN16
// ============================================================================
// implementation of global private functions
// ============================================================================
+
bool KeyExists(WXHKEY hRootKey, const wxChar *szKey)
{
+ // don't close this key itself for the case of empty szKey!
+ if ( wxIsEmpty(szKey) )
+ return TRUE;
+
HKEY hkeyDummy;
if ( RegOpenKey( (HKEY) hRootKey, szKey, &hkeyDummy) == ERROR_SUCCESS ) {
RegCloseKey(hkeyDummy);