X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6f94aa869d07fd18ed16f8bb237f13fed2da6185..12bb29f5432174ecbd65549bda832d70d34a98ae:/src/msw/registry.cpp diff --git a/src/msw/registry.cpp b/src/msw/registry.cpp index 2607a3f2c7..144009b810 100644 --- a/src/msw/registry.cpp +++ b/src/msw/registry.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: msw/registry.cpp +// Name: src/msw/registry.cpp // Purpose: implementation of registry classes and functions // Author: Vadim Zeitlin // Modified by: @@ -12,29 +12,31 @@ // - add high level functions (RegisterOleServer, ...) /////////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "registry.h" -#endif - // for compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif -// other wxWidgets headers -#include "wx/string.h" -#include "wx/intl.h" -#include "wx/log.h" -#include "wx/file.h" -#include "wx/wfstream.h" +#if wxUSE_REGKEY -// Windows headers -#include "wx/msw/wrapwin.h" +#ifndef WX_PRECOMP + #include "wx/msw/wrapwin.h" + #include "wx/string.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/crt.h" + #include "wx/utils.h" +#endif -#ifdef __WXWINCE__ +#include "wx/dynlib.h" +#include "wx/file.h" +#include "wx/wfstream.h" #include "wx/msw/private.h" + +// Windows headers +#ifdef __WXWINCE__ #include #include #endif @@ -54,6 +56,22 @@ typedef unsigned char *RegString; typedef BYTE* RegBinary; +#ifndef HKEY_PERFORMANCE_DATA + #define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004) +#endif + +#ifndef HKEY_CURRENT_CONFIG + #define HKEY_CURRENT_CONFIG ((HKEY)0x80000005) +#endif + +#ifndef HKEY_DYN_DATA + #define HKEY_DYN_DATA ((HKEY)0x80000006) +#endif + +#ifndef KEY_WOW64_64KEY + #define KEY_WOW64_64KEY 0x0100 +#endif + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -72,15 +90,9 @@ aStdKeys[] = { HKEY_CURRENT_USER, wxT("HKEY_CURRENT_USER"), wxT("HKCU") }, { HKEY_LOCAL_MACHINE, wxT("HKEY_LOCAL_MACHINE"), wxT("HKLM") }, { HKEY_USERS, wxT("HKEY_USERS"), wxT("HKU") }, // short name? -#ifndef __WXWINCE__ { HKEY_PERFORMANCE_DATA, wxT("HKEY_PERFORMANCE_DATA"), wxT("HKPD") }, -#endif -#ifdef HKEY_CURRENT_CONFIG { HKEY_CURRENT_CONFIG, wxT("HKEY_CURRENT_CONFIG"), wxT("HKCC") }, -#endif -#ifdef HKEY_DYN_DATA { HKEY_DYN_DATA, wxT("HKEY_DYN_DATA"), wxT("HKDD") }, // short name? -#endif }; // the registry name separator (perhaps one day MS will change it to '/' ;-) @@ -108,11 +120,28 @@ aStdKeys[] = static inline void RemoveTrailingSeparator(wxString& str); // returns true if given registry key exists -static bool KeyExists(WXHKEY hRootKey, const wxChar *szKey); +static bool KeyExists( + WXHKEY hRootKey, + const wxString& szKey, + wxRegKey::WOW64ViewMode viewMode = wxRegKey::WOW64ViewMode_Default); + +// return the WOW64 registry view flag which can be used with MSW registry +// functions for opening the key in the specified view +static long GetMSWViewFlags(wxRegKey::WOW64ViewMode viewMode); + +// return the access rights which can be used with MSW registry functions for +// opening the key in the specified mode +static long +GetMSWAccessFlags(wxRegKey::AccessMode mode, wxRegKey::WOW64ViewMode viewMode); + +// combines value and key name +static wxString GetFullName(const wxRegKey *pKey); +static wxString GetFullName(const wxRegKey *pKey, const wxString& szValue); -// combines value and key name (uses static buffer!) -static const wxChar *GetFullName(const wxRegKey *pKey, - const wxChar *szValue = NULL); +// returns "value" argument of wxRegKey methods converted into a value that can +// be passed to win32 registry functions; specifically, converts empty string +// to NULL +static inline const wxChar *RegValueStr(const wxString& szValue); // ============================================================================ // implementation of wxRegKey class @@ -146,12 +175,10 @@ wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey) { wxString strRoot = strKey.BeforeFirst(REG_SEPARATOR); - HKEY hRootKey = 0; size_t ui; for ( ui = 0; ui < nStdKeys; ui++ ) { if ( strRoot.CmpNoCase(aStdKeys[ui].szName) == 0 || strRoot.CmpNoCase(aStdKeys[ui].szShortName) == 0 ) { - hRootKey = aStdKeys[ui].hkey; break; } } @@ -159,21 +186,21 @@ wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey) if ( ui == nStdKeys ) { wxFAIL_MSG(wxT("invalid key prefix in wxRegKey::ExtractKeyName.")); - hRootKey = HKEY_CLASSES_ROOT; + ui = HKCR; } else { strKey = strKey.After(REG_SEPARATOR); - if ( !strKey.IsEmpty() && strKey.Last() == REG_SEPARATOR ) + if ( !strKey.empty() && strKey.Last() == REG_SEPARATOR ) strKey.Truncate(strKey.Len() - 1); } - return (wxRegKey::StdKey)(int)hRootKey; + return (StdKey)ui; } wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(WXHKEY hkey) { for ( size_t ui = 0; ui < nStdKeys; ui++ ) { - if ( (int) aStdKeys[ui].hkey == (int) hkey ) + if ( aStdKeys[ui].hkey == (HKEY)hkey ) return (StdKey)ui; } @@ -186,14 +213,15 @@ wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(WXHKEY hkey) // ctors and dtor // ---------------------------------------------------------------------------- -wxRegKey::wxRegKey() +wxRegKey::wxRegKey(WOW64ViewMode viewMode) : m_viewMode(viewMode) { m_hRootKey = (WXHKEY) aStdKeys[HKCR].hkey; Init(); } -wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey) +wxRegKey::wxRegKey(const wxString& strKey, WOW64ViewMode viewMode) + : m_strKey(strKey), m_viewMode(viewMode) { m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey; @@ -201,7 +229,10 @@ wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey) } // parent is a predefined (and preopened) key -wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey) +wxRegKey::wxRegKey(StdKey keyParent, + const wxString& strKey, + WOW64ViewMode viewMode) + : m_strKey(strKey), m_viewMode(viewMode) { RemoveTrailingSeparator(m_strKey); m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey; @@ -211,11 +242,11 @@ wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey) // parent is a normal regkey wxRegKey::wxRegKey(const wxRegKey& keyParent, const wxString& strKey) - : m_strKey(keyParent.m_strKey) + : m_strKey(keyParent.m_strKey), m_viewMode(keyParent.GetView()) { // combine our name with parent's to get the full name - if ( !m_strKey.IsEmpty() && - (strKey.IsEmpty() || strKey[0] != REG_SEPARATOR) ) { + if ( !m_strKey.empty() && + (strKey.empty() || strKey[0] != REG_SEPARATOR) ) { m_strKey += REG_SEPARATOR; } @@ -270,7 +301,7 @@ void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey) // next line! m_strKey.clear(); m_strKey += keyParent.m_strKey; - if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR ) + if ( !strKey.empty() && strKey[0] != REG_SEPARATOR ) m_strKey += REG_SEPARATOR; m_strKey += strKey; @@ -285,6 +316,18 @@ void wxRegKey::SetHkey(WXHKEY hKey) Close(); m_hKey = hKey; + + // we don't know the parent of this key, assume HKLM by default + m_hRootKey = HKEY_LOCAL_MACHINE; + + // we don't know in which mode was this key opened but we can't reopen it + // anyhow because we don't know its name, so the only thing we can is to hope + // that it allows all the operations which we're going to perform on it + m_mode = Write; + + // reset old data + m_strKey.clear(); + m_dwLastError = 0; } // ---------------------------------------------------------------------------- @@ -295,7 +338,9 @@ void wxRegKey::SetHkey(WXHKEY hKey) bool wxRegKey::Exists() const { // opened key has to exist, try to open it if not done yet - return IsOpened() ? true : KeyExists(m_hRootKey, m_strKey); + return IsOpened() + ? true + : KeyExists(m_hRootKey, m_strKey, m_viewMode); } // returns the full name of the key (prefix is abbreviated if bShortPrefix) @@ -304,8 +349,8 @@ wxString wxRegKey::GetName(bool bShortPrefix) const StdKey key = GetStdKeyFromHkey((WXHKEY) m_hRootKey); wxString str = bShortPrefix ? aStdKeys[key].szShortName : aStdKeys[key].szName; - if ( !m_strKey.IsEmpty() ) - str << _T("\\") << m_strKey; + if ( !m_strKey.empty() ) + str << wxT("\\") << m_strKey; return str; } @@ -315,36 +360,57 @@ bool wxRegKey::GetKeyInfo(size_t *pnSubKeys, size_t *pnValues, size_t *pnMaxValueLen) const { - // old gcc headers incorrectly prototype RegQueryInfoKey() -#if defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__) - #define REG_PARAM (size_t *) -#else - #define REG_PARAM (LPDWORD) + // it might be unexpected to some that this function doesn't open the key + wxASSERT_MSG( IsOpened(), wxT("key should be opened in GetKeyInfo") ); + + // We need to use intermediate variables in 64 bit build as the function + // parameters must be 32 bit DWORDs and not 64 bit size_t values. +#ifdef __WIN64__ + DWORD dwSubKeys = 0, + dwMaxKeyLen = 0, + dwValues = 0, + dwMaxValueLen = 0; + + #define REG_PARAM(name) &dw##name +#else // Win32 + // Old gcc headers incorrectly prototype RegQueryInfoKey() as taking + // size_t but normally we need a cast, even when sizeof(size_t) is the same + // as sizeof(DWORD). + #if defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__) + #define REG_PARAM(name) pn##name + #else + #define REG_PARAM(name) (LPDWORD)(pn##name) + #endif #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, - NULL, // class name - NULL, // (ptr to) size of class name buffer + NULL, // class name + NULL, // (ptr to) size of class name buffer RESERVED, - REG_PARAM - pnSubKeys, // [out] number of subkeys - REG_PARAM - pnMaxKeyLen, // [out] max length of a subkey name - NULL, // longest subkey class name - REG_PARAM - pnValues, // [out] number of values - REG_PARAM - pnMaxValueLen, // [out] max length of a value name - NULL, // longest value data - NULL, // security descriptor - NULL // time of last modification + REG_PARAM(SubKeys), // [out] number of subkeys + REG_PARAM(MaxKeyLen), // [out] max length of a subkey name + NULL, // longest subkey class name + REG_PARAM(Values), // [out] number of values + REG_PARAM(MaxValueLen), // [out] max length of a value name + NULL, // longest value data + NULL, // security descriptor + NULL // time of last modification ); +#ifdef __WIN64__ + if ( pnSubKeys ) + *pnSubKeys = dwSubKeys; + if ( pnMaxKeyLen ) + *pnMaxKeyLen = dwMaxKeyLen; + if ( pnValues ) + *pnValues = dwValues; + if ( pnMaxValueLen ) + *pnMaxValueLen = dwMaxValueLen; +#endif // __WIN64__ + #undef REG_PARAM if ( m_dwLastError != ERROR_SUCCESS ) { @@ -376,9 +442,9 @@ bool wxRegKey::Open(AccessMode mode) m_dwLastError = ::RegOpenKeyEx ( (HKEY) m_hRootKey, - m_strKey, + m_strKey.t_str(), RESERVED, - mode == Read ? KEY_READ : KEY_ALL_ACCESS, + GetMSWAccessFlags(mode, m_viewMode), &tmpKey ); @@ -406,19 +472,17 @@ bool wxRegKey::Create(bool bOkIfExists) return true; HKEY tmpKey; -#ifdef __WXWINCE__ DWORD disposition; - m_dwLastError = RegCreateKeyEx((HKEY) m_hRootKey, m_strKey, - NULL, // reserved - NULL, // class string - 0, - 0, - NULL, + // Minimum supported OS for RegCreateKeyEx: Win 95, Win NT 3.1, Win CE 1.0 + m_dwLastError = RegCreateKeyEx((HKEY) m_hRootKey, m_strKey.t_str(), + 0, // reserved and must be 0 + NULL, // The user-defined class type of this key. + REG_OPTION_NON_VOLATILE, // supports other values as well; see MS docs + GetMSWAccessFlags(wxRegKey::Write, m_viewMode), + NULL, // pointer to a SECURITY_ATTRIBUTES structure &tmpKey, &disposition); -#else - m_dwLastError = RegCreateKey((HKEY) m_hRootKey, m_strKey, &tmpKey); -#endif + if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't create registry key '%s'"), GetName().c_str()); @@ -449,7 +513,8 @@ bool wxRegKey::Close() return true; } -bool wxRegKey::RenameValue(const wxChar *szValueOld, const wxChar *szValueNew) +bool +wxRegKey::RenameValue(const wxString& szValueOld, const wxString& szValueNew) { bool ok = true; if ( HasValue(szValueNew) ) { @@ -470,13 +535,14 @@ bool wxRegKey::RenameValue(const wxChar *szValueOld, const wxChar *szValueNew) return true; } -bool wxRegKey::CopyValue(const wxChar *szValue, +bool wxRegKey::CopyValue(const wxString& szValue, wxRegKey& keyDst, - const wxChar *szValueNew) + const wxString& szValueNew) { - if ( !szValueNew ) { + wxString valueNew(szValueNew); + if ( valueNew.empty() ) { // by default, use the same name - szValueNew = szValue; + valueNew = szValue; } switch ( GetValueType(szValue) ) { @@ -484,7 +550,7 @@ bool wxRegKey::CopyValue(const wxChar *szValue, { wxString strVal; return QueryValue(szValue, strVal) && - keyDst.SetValue(szValueNew, strVal); + keyDst.SetValue(valueNew, strVal); } case Type_Dword: @@ -492,14 +558,14 @@ bool wxRegKey::CopyValue(const wxChar *szValue, { long dwVal; return QueryValue(szValue, &dwVal) && - keyDst.SetValue(szValueNew, dwVal); + keyDst.SetValue(valueNew, dwVal); } case Type_Binary: { wxMemoryBuffer buf; return QueryValue(szValue,buf) && - keyDst.SetValue(szValueNew,buf); + keyDst.SetValue(valueNew,buf); } // these types are unsupported because I am not sure about how @@ -521,9 +587,9 @@ bool wxRegKey::CopyValue(const wxChar *szValue, } } -bool wxRegKey::Rename(const wxChar *szNewName) +bool wxRegKey::Rename(const wxString& szNewName) { - wxCHECK_MSG( !m_strKey.IsEmpty(), false, _T("registry hives can't be renamed") ); + wxCHECK_MSG( !m_strKey.empty(), false, wxT("registry hives can't be renamed") ); if ( !Exists() ) { wxLogError(_("Registry key '%s' does not exist, cannot rename it."), @@ -541,7 +607,7 @@ bool wxRegKey::Rename(const wxChar *szNewName) if ( inSameHive ) { // rename the key to the new name under the same parent wxString strKey = m_strKey.BeforeLast(REG_SEPARATOR); - if ( !strKey.IsEmpty() ) { + if ( !strKey.empty() ) { // don't add '\\' in the start if strFullNewName is empty strKey += REG_SEPARATOR; } @@ -576,7 +642,7 @@ bool wxRegKey::Rename(const wxChar *szNewName) return ok; } -bool wxRegKey::Copy(const wxChar *szNewName) +bool wxRegKey::Copy(const wxString& szNewName) { // create the new key first wxRegKey keyDst(szNewName); @@ -605,7 +671,7 @@ bool wxRegKey::Copy(wxRegKey& keyDst) wxRegKey key(*this, strKey); wxString keyName; keyName << GetFullName(&keyDst) << REG_SEPARATOR << strKey; - ok = key.Copy((const wxChar*) keyName); + ok = key.Copy(keyName); if ( ok ) bCont = GetNextKey(strKey, lIndex); @@ -655,7 +721,7 @@ bool wxRegKey::DeleteSelf() // 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() || + if ( m_strKey.empty() || ((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."), @@ -687,8 +753,25 @@ bool wxRegKey::DeleteSelf() // now delete this key itself Close(); - m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey); // deleting a key which doesn't exist is not considered an error +#if wxUSE_DYNLIB_CLASS + wxDynamicLibrary dllAdvapi32(wxT("advapi32")); + // Minimum supported OS for RegDeleteKeyEx: Vista, XP Pro x64, Win Server 2008, Win Server 2003 SP1 + if(dllAdvapi32.HasSymbol(wxT("RegDeleteKeyEx"))) + { + typedef LONG (WINAPI *RegDeleteKeyEx_t)(HKEY, LPCTSTR, REGSAM, DWORD); + wxDYNLIB_FUNCTION(RegDeleteKeyEx_t, RegDeleteKeyEx, dllAdvapi32); + + m_dwLastError = (*pfnRegDeleteKeyEx)((HKEY) m_hRootKey, m_strKey.t_str(), + GetMSWViewFlags(m_viewMode), + 0); // This parameter is reserved and must be zero. + } + else +#endif // wxUSE_DYNLIB_CLASS + { + m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey.t_str()); + } + if ( m_dwLastError != ERROR_SUCCESS && m_dwLastError != ERROR_FILE_NOT_FOUND ) { wxLogSysError(m_dwLastError, _("Can't delete key '%s'"), @@ -699,7 +782,7 @@ bool wxRegKey::DeleteSelf() return true; } -bool wxRegKey::DeleteKey(const wxChar *szKey) +bool wxRegKey::DeleteKey(const wxString& szKey) { if ( !Open() ) return false; @@ -708,22 +791,23 @@ bool wxRegKey::DeleteKey(const wxChar *szKey) return key.DeleteSelf(); } -bool wxRegKey::DeleteValue(const wxChar *szValue) +bool wxRegKey::DeleteValue(const wxString& szValue) { - if ( !Open() ) - return false; + if ( !Open() ) + return false; - m_dwLastError = RegDeleteValue((HKEY) m_hKey, WXSTRINGCAST szValue); + m_dwLastError = RegDeleteValue((HKEY) m_hKey, RegValueStr(szValue)); // deleting a value which doesn't exist is not considered an error if ( (m_dwLastError != ERROR_SUCCESS) && - (m_dwLastError != ERROR_FILE_NOT_FOUND) ) { - wxLogSysError(m_dwLastError, _("Can't delete value '%s' from key '%s'"), - szValue, GetName().c_str()); - return false; + (m_dwLastError != ERROR_FILE_NOT_FOUND) ) + { + wxLogSysError(m_dwLastError, _("Can't delete value '%s' from key '%s'"), + szValue, GetName().c_str()); + return false; } - return true; + return true; } // ---------------------------------------------------------------------------- @@ -731,16 +815,16 @@ bool wxRegKey::DeleteValue(const wxChar *szValue) // ---------------------------------------------------------------------------- // return true if value exists -bool wxRegKey::HasValue(const wxChar *szValue) const +bool wxRegKey::HasValue(const wxString& szValue) const { - // this function should be silent, so suppress possible messages from Open() - wxLogNull nolog; + // this function should be silent, so suppress possible messages from Open() + wxLogNull nolog; if ( !CONST_CAST Open(Read) ) return false; LONG dwRet = ::RegQueryValueEx((HKEY) m_hKey, - WXSTRINGCAST szValue, + RegValueStr(szValue), RESERVED, NULL, NULL, NULL); return dwRet == ERROR_SUCCESS; @@ -771,7 +855,7 @@ bool wxRegKey::HasSubkeys() const } // returns true if given subkey exists -bool wxRegKey::HasSubKey(const wxChar *szKey) const +bool wxRegKey::HasSubKey(const wxString& szKey) const { // this function should be silent, so suppress possible messages from Open() wxLogNull nolog; @@ -779,16 +863,16 @@ bool wxRegKey::HasSubKey(const wxChar *szKey) const if ( !CONST_CAST Open(Read) ) return false; - return KeyExists(m_hKey, szKey); + return KeyExists(m_hKey, szKey, m_viewMode); } -wxRegKey::ValueType wxRegKey::GetValueType(const wxChar *szValue) const +wxRegKey::ValueType wxRegKey::GetValueType(const wxString& szValue) const { if ( ! CONST_CAST Open(Read) ) return Type_None; DWORD dwType; - m_dwLastError = RegQueryValueEx((HKEY) m_hKey, WXSTRINGCAST szValue, RESERVED, + m_dwLastError = RegQueryValueEx((HKEY) m_hKey, RegValueStr(szValue), RESERVED, &dwType, NULL, NULL); if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't read value of key '%s'"), @@ -799,10 +883,11 @@ wxRegKey::ValueType wxRegKey::GetValueType(const wxChar *szValue) const return (ValueType)dwType; } -bool wxRegKey::SetValue(const wxChar *szValue, long lValue) +bool wxRegKey::SetValue(const wxString& szValue, long lValue) { if ( CONST_CAST Open() ) { - m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, (DWORD) RESERVED, REG_DWORD, + m_dwLastError = RegSetValueEx((HKEY) m_hKey, RegValueStr(szValue), + (DWORD) RESERVED, REG_DWORD, (RegString)&lValue, sizeof(lValue)); if ( m_dwLastError == ERROR_SUCCESS ) return true; @@ -813,12 +898,13 @@ bool wxRegKey::SetValue(const wxChar *szValue, long lValue) return false; } -bool wxRegKey::QueryValue(const wxChar *szValue, long *plValue) const +bool wxRegKey::QueryValue(const wxString& szValue, long *plValue) const { if ( CONST_CAST Open(Read) ) { DWORD dwType, dwSize = sizeof(DWORD); RegString pBuf = (RegString)plValue; - m_dwLastError = RegQueryValueEx((HKEY) m_hKey, WXSTRINGCAST szValue, RESERVED, + m_dwLastError = RegQueryValueEx((HKEY) m_hKey, RegValueStr(szValue), + RESERVED, &dwType, pBuf, &dwSize); if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't read value of key '%s'"), @@ -837,14 +923,15 @@ bool wxRegKey::QueryValue(const wxChar *szValue, long *plValue) const return false; } -bool wxRegKey::SetValue(const wxChar *szValue,const wxMemoryBuffer& buffer) +bool wxRegKey::SetValue(const wxString& szValue, const wxMemoryBuffer& buffer) { #ifdef __TWIN32__ wxFAIL_MSG("RegSetValueEx not implemented by TWIN32"); return false; #else if ( CONST_CAST Open() ) { - m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, (DWORD) RESERVED, REG_BINARY, + m_dwLastError = RegSetValueEx((HKEY) m_hKey, RegValueStr(szValue), + (DWORD) RESERVED, REG_BINARY, (RegBinary)buffer.GetData(),buffer.GetDataLen()); if ( m_dwLastError == ERROR_SUCCESS ) return true; @@ -856,19 +943,20 @@ bool wxRegKey::SetValue(const wxChar *szValue,const wxMemoryBuffer& buffer) #endif } -bool wxRegKey::QueryValue(const wxChar *szValue, wxMemoryBuffer& buffer) const +bool wxRegKey::QueryValue(const wxString& szValue, wxMemoryBuffer& buffer) const { - if ( CONST_CAST Open() ) { + if ( CONST_CAST Open(Read) ) { // first get the type and size of the data DWORD dwType, dwSize; - m_dwLastError = RegQueryValueEx((HKEY) m_hKey, WXSTRINGCAST szValue, RESERVED, - &dwType, NULL, &dwSize); + m_dwLastError = RegQueryValueEx((HKEY) m_hKey, RegValueStr(szValue), + RESERVED, + &dwType, NULL, &dwSize); if ( m_dwLastError == ERROR_SUCCESS ) { if ( dwSize ) { const RegBinary pBuf = (RegBinary)buffer.GetWriteBuf(dwSize); m_dwLastError = RegQueryValueEx((HKEY) m_hKey, - WXSTRINGCAST szValue, + RegValueStr(szValue), RESERVED, &dwType, pBuf, @@ -892,79 +980,84 @@ bool wxRegKey::QueryValue(const wxChar *szValue, wxMemoryBuffer& buffer) const -bool wxRegKey::QueryValue(const wxChar *szValue, +bool wxRegKey::QueryValue(const wxString& szValue, wxString& strValue, - bool raw) const + bool WXUNUSED_IN_WINCE(raw)) const { - if ( CONST_CAST Open(Read) ) { - - // first get the type and size of the data - DWORD dwType, dwSize; - m_dwLastError = RegQueryValueEx((HKEY) m_hKey, WXSTRINGCAST szValue, RESERVED, - &dwType, NULL, &dwSize); - if ( m_dwLastError == ERROR_SUCCESS ) { - if ( !dwSize ) { - // must treat this case specially as GetWriteBuf() doesn't like - // being called with 0 size - strValue.Empty(); - } - else { - m_dwLastError = RegQueryValueEx((HKEY) m_hKey, - WXSTRINGCAST szValue, - RESERVED, - &dwType, - (RegString)(wxChar*)wxStringBuffer(strValue, dwSize), - &dwSize); + if ( CONST_CAST Open(Read) ) + { - // expand the var expansions in the string unless disabled -#ifndef __WXWINCE__ - if ( (dwType == REG_EXPAND_SZ) && !raw ) + // first get the type and size of the data + DWORD dwType=REG_NONE, dwSize=0; + m_dwLastError = RegQueryValueEx((HKEY) m_hKey, + RegValueStr(szValue), + RESERVED, + &dwType, NULL, &dwSize); + if ( m_dwLastError == ERROR_SUCCESS ) + { + if ( !dwSize ) + { + // must treat this case specially as GetWriteBuf() doesn't like + // being called with 0 size + strValue.Empty(); + } + else { - DWORD dwExpSize = ::ExpandEnvironmentStrings(strValue, NULL, 0); - bool ok = dwExpSize != 0; - if ( ok ) + m_dwLastError = RegQueryValueEx((HKEY) m_hKey, + RegValueStr(szValue), + RESERVED, + &dwType, + (RegString)(wxChar*)wxStringBuffer(strValue, dwSize), + &dwSize); + + // expand the var expansions in the string unless disabled +#ifndef __WXWINCE__ + if ( (dwType == REG_EXPAND_SZ) && !raw ) { - wxString strExpValue; - ok = ::ExpandEnvironmentStrings - ( - strValue, - wxStringBuffer(strExpValue, dwExpSize), - dwExpSize - ) != 0; - strValue = strExpValue; - } + DWORD dwExpSize = ::ExpandEnvironmentStrings(strValue.t_str(), NULL, 0); + bool ok = dwExpSize != 0; + if ( ok ) + { + wxString strExpValue; + ok = ::ExpandEnvironmentStrings(strValue.t_str(), + wxStringBuffer(strExpValue, dwExpSize), + dwExpSize + ) != 0; + strValue = strExpValue; + } - if ( !ok ) - { - wxLogLastError(_T("ExpandEnvironmentStrings")); + if ( !ok ) + { + wxLogLastError(wxT("ExpandEnvironmentStrings")); + } } - } -#else - wxUnusedVar(raw); #endif - // __WXWINCE__ - } + // __WXWINCE__ + } - if ( m_dwLastError == ERROR_SUCCESS ) { - // check that it was the right type - wxASSERT_MSG( !IsNumericValue(szValue), - wxT("Type mismatch in wxRegKey::QueryValue().") ); + if ( m_dwLastError == ERROR_SUCCESS ) + { + // check that it was the right type + wxASSERT_MSG( !IsNumericValue(szValue), + wxT("Type mismatch in wxRegKey::QueryValue().") ); - return true; + return true; + } } - } - } + } - wxLogSysError(m_dwLastError, _("Can't read value of '%s'"), - GetFullName(this, szValue)); - return false; + wxLogSysError(m_dwLastError, _("Can't read value of '%s'"), + GetFullName(this, szValue)); + return false; } -bool wxRegKey::SetValue(const wxChar *szValue, const wxString& strValue) +bool wxRegKey::SetValue(const wxString& szValue, const wxString& strValue) { if ( CONST_CAST Open() ) { - m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, (DWORD) RESERVED, REG_SZ, - (RegString)strValue.c_str(), + m_dwLastError = RegSetValueEx((HKEY) m_hKey, + RegValueStr(szValue), + (DWORD) RESERVED, REG_SZ, + (RegString)wxMSW_CONV_LPCTSTR(strValue), (strValue.Len() + 1)*sizeof(wxChar)); if ( m_dwLastError == ERROR_SUCCESS ) return true; @@ -978,7 +1071,7 @@ bool wxRegKey::SetValue(const wxChar *szValue, const wxString& strValue) wxString wxRegKey::QueryDefaultValue() const { wxString str; - QueryValue(NULL, str); + QueryValue(wxEmptyString, str, false); return str; } @@ -1078,7 +1171,7 @@ bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const } // returns true if the value contains a number (else it's some string) -bool wxRegKey::IsNumericValue(const wxChar *szValue) const +bool wxRegKey::IsNumericValue(const wxString& szValue) const { ValueType type = GetValueType(szValue); switch ( type ) { @@ -1096,6 +1189,8 @@ bool wxRegKey::IsNumericValue(const wxChar *szValue) const // exporting registry keys to file // ---------------------------------------------------------------------------- +#if wxUSE_STREAMS + // helper functions for writing ASCII strings (even in Unicode build) static inline bool WriteAsciiChar(wxOutputStream& ostr, char ch) { @@ -1120,14 +1215,17 @@ static inline bool WriteAsciiString(wxOutputStream& ostr, const wxString& s) wxCharBuffer name(s.mb_str()); ostr.Write(name, strlen(name)); #else - ostr.Write(s, s.length()); + ostr.Write(s.mb_str(), s.length()); #endif return ostr.IsOk(); } +#endif // wxUSE_STREAMS + bool wxRegKey::Export(const wxString& filename) const { +#if wxUSE_FFILE && wxUSE_STREAMS if ( wxFile::Exists(filename) ) { wxLogError(_("Exporting registry key: file \"%s\" already exists and won't be overwritten."), @@ -1135,11 +1233,16 @@ bool wxRegKey::Export(const wxString& filename) const return false; } - wxFFileOutputStream ostr(filename, _T("w")); + wxFFileOutputStream ostr(filename, wxT("w")); - return ostr.Ok() && Export(ostr); + return ostr.IsOk() && Export(ostr); +#else + wxUnusedVar(filename); + return false; +#endif } +#if wxUSE_STREAMS bool wxRegKey::Export(wxOutputStream& ostr) const { // write out the header @@ -1148,6 +1251,7 @@ bool wxRegKey::Export(wxOutputStream& ostr) const return DoExport(ostr); } +#endif // wxUSE_STREAMS static wxString @@ -1155,26 +1259,26 @@ FormatAsHex(const void *data, size_t size, wxRegKey::ValueType type = wxRegKey::Type_Binary) { - wxString value(_T("hex")); + wxString value(wxT("hex")); // binary values use just "hex:" prefix while the other ones must indicate // the real type if ( type != wxRegKey::Type_Binary ) - value << _T('(') << type << _T(')'); - value << _T(':'); + value << wxT('(') << type << wxT(')'); + value << wxT(':'); // write all the rest as comma-separated bytes value.reserve(3*size + 10); - const char * const p = wx_static_cast(const char *, data); + const char * const p = static_cast(data); for ( size_t n = 0; n < size; n++ ) { // TODO: line wrapping: although not required by regedit, this makes // the generated files easier to read and compare with the files // produced by regedit if ( n ) - value << _T(','); + value << wxT(','); - value << wxString::Format(_T("%02x"), (unsigned char)p[n]); + value << wxString::Format(wxT("%02x"), (unsigned char)p[n]); } return value; @@ -1201,23 +1305,24 @@ wxString wxRegKey::FormatValue(const wxString& name) const // quotes and backslashes must be quoted, linefeeds are not // allowed in string values rhs.reserve(value.length() + 2); - rhs = _T('"'); + rhs = wxT('"'); // there can be no NULs here bool useHex = false; - for ( const wxChar *p = value.c_str(); *p && !useHex; p++ ) + for ( wxString::const_iterator p = value.begin(); + p != value.end() && !useHex; ++p ) { - switch ( *p ) + switch ( (*p).GetValue() ) { - case _T('\n'): + case wxT('\n'): // we can only represent this string in hex useHex = true; break; - case _T('"'): - case _T('\\'): + case wxT('"'): + case wxT('\\'): // escape special symbol - rhs += _T('\\'); + rhs += wxT('\\'); // fall through default: @@ -1228,7 +1333,7 @@ wxString wxRegKey::FormatValue(const wxString& name) const if ( useHex ) rhs = FormatAsHex(value, Type_String); else - rhs += _T('"'); + rhs += wxT('"'); } break; @@ -1239,7 +1344,7 @@ wxString wxRegKey::FormatValue(const wxString& name) const if ( !QueryValue(name, &value) ) break; - rhs.Printf(_T("dword:%08x"), (unsigned int)value); + rhs.Printf(wxT("dword:%08x"), (unsigned int)value); } break; @@ -1278,6 +1383,8 @@ wxString wxRegKey::FormatValue(const wxString& name) const return rhs; } +#if wxUSE_STREAMS + bool wxRegKey::DoExportValue(wxOutputStream& ostr, const wxString& name) const { // first examine the value type: if it's unsupported, simply skip it @@ -1329,7 +1436,7 @@ bool wxRegKey::DoExport(wxOutputStream& ostr) const // dump all our values long dummy; wxString name; - wxRegKey& self = wx_const_cast(wxRegKey&, *this); + wxRegKey& self = const_cast(*this); bool cont = self.GetFirstValue(name, dummy); while ( cont ) { @@ -1357,23 +1464,28 @@ bool wxRegKey::DoExport(wxOutputStream& ostr) const return true; } +#endif // wxUSE_STREAMS + // ============================================================================ // implementation of global private functions // ============================================================================ -bool KeyExists(WXHKEY hRootKey, const wxChar *szKey) +bool KeyExists(WXHKEY hRootKey, + const wxString& szKey, + wxRegKey::WOW64ViewMode viewMode) { // don't close this key itself for the case of empty szKey! - if ( wxIsEmpty(szKey) ) + if ( szKey.empty() ) return true; HKEY hkeyDummy; if ( ::RegOpenKeyEx ( (HKEY)hRootKey, - szKey, + szKey.t_str(), RESERVED, - KEY_READ, // we might not have enough rights for rw access + // we might not have enough rights for rw access + GetMSWAccessFlags(wxRegKey::Read, viewMode), &hkeyDummy ) == ERROR_SUCCESS ) { @@ -1385,19 +1497,72 @@ bool KeyExists(WXHKEY hRootKey, const wxChar *szKey) return false; } -const wxChar *GetFullName(const wxRegKey *pKey, const wxChar *szValue) +long GetMSWViewFlags(wxRegKey::WOW64ViewMode viewMode) { - static wxString s_str; - s_str = pKey->GetName(); - if ( !wxIsEmpty(szValue) ) - s_str << wxT("\\") << szValue; + long samWOW64ViewMode = 0; - return s_str.c_str(); + switch ( viewMode ) + { + case wxRegKey::WOW64ViewMode_32: +#ifdef __WIN64__ // the flag is only needed by 64 bit apps + samWOW64ViewMode = KEY_WOW64_32KEY; +#endif // Win64 + break; + + case wxRegKey::WOW64ViewMode_64: +#ifndef __WIN64__ // the flag is only needed by 32 bit apps + // 64 bit registry can only be accessed under 64 bit platforms + if ( wxIsPlatform64Bit() ) + samWOW64ViewMode = KEY_WOW64_64KEY; +#endif // Win32 + break; + + default: + wxFAIL_MSG("Unknown registry view."); + // fall through + + case wxRegKey::WOW64ViewMode_Default: + // Use default registry view for the current application, + // i.e. 32 bits for 32 bit ones and 64 bits for 64 bit apps + ; + } + + return samWOW64ViewMode; } -void RemoveTrailingSeparator(wxString& str) +long GetMSWAccessFlags(wxRegKey::AccessMode mode, + wxRegKey::WOW64ViewMode viewMode) { - if ( !str.IsEmpty() && str.Last() == REG_SEPARATOR ) + long sam = mode == wxRegKey::Read ? KEY_READ : KEY_ALL_ACCESS; + + sam |= GetMSWViewFlags(viewMode); + + return sam; +} + +wxString GetFullName(const wxRegKey *pKey, const wxString& szValue) +{ + wxString str(pKey->GetName()); + if ( !szValue.empty() ) + str << wxT("\\") << szValue; + + return str; +} + +wxString GetFullName(const wxRegKey *pKey) +{ + return pKey->GetName(); +} + +inline void RemoveTrailingSeparator(wxString& str) +{ + if ( !str.empty() && str.Last() == REG_SEPARATOR ) str.Truncate(str.Len() - 1); } +inline const wxChar *RegValueStr(const wxString& szValue) +{ + return szValue.empty() ? (const wxChar*)NULL : szValue.t_str(); +} + +#endif // wxUSE_REGKEY