X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c6867dcd5110058c0e63a8de5f05fdc139c18129..1ce077e25b52782f7823b7372664db76a9aa96c9:/src/msw/registry.cpp diff --git a/src/msw/registry.cpp b/src/msw/registry.cpp index 29c4479842..83d11c2769 100644 --- a/src/msw/registry.cpp +++ b/src/msw/registry.cpp @@ -27,8 +27,10 @@ #include "wx/intl.h" #include "wx/log.h" #include "wx/crt.h" + #include "wx/utils.h" #endif +#include "wx/dynlib.h" #include "wx/file.h" #include "wx/wfstream.h" @@ -66,6 +68,10 @@ typedef BYTE* RegBinary; #define HKEY_DYN_DATA ((HKEY)0x80000006) #endif +#ifndef KEY_WOW64_64KEY + #define KEY_WOW64_64KEY 0x0100 +#endif + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -114,7 +120,19 @@ aStdKeys[] = static inline void RemoveTrailingSeparator(wxString& str); // returns true if given registry key exists -static bool KeyExists(WXHKEY hRootKey, const wxString& 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); @@ -195,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; @@ -210,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; @@ -220,7 +242,7 @@ 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.empty() && @@ -294,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.empty(); + m_dwLastError = 0; } // ---------------------------------------------------------------------------- @@ -304,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.wx_str()); + return IsOpened() + ? true + : KeyExists(m_hRootKey, m_strKey, m_viewMode); } // returns the full name of the key (prefix is abbreviated if bShortPrefix) @@ -314,7 +350,7 @@ wxString wxRegKey::GetName(bool bShortPrefix) const wxString str = bShortPrefix ? aStdKeys[key].szShortName : aStdKeys[key].szName; if ( !m_strKey.empty() ) - str << _T("\\") << m_strKey; + str << wxT("\\") << m_strKey; return str; } @@ -324,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 ) { @@ -385,9 +442,9 @@ bool wxRegKey::Open(AccessMode mode) m_dwLastError = ::RegOpenKeyEx ( (HKEY) m_hRootKey, - m_strKey.wc_str(), + m_strKey.t_str(), RESERVED, - mode == Read ? KEY_READ : KEY_ALL_ACCESS, + GetMSWAccessFlags(mode, m_viewMode), &tmpKey ); @@ -415,19 +472,17 @@ bool wxRegKey::Create(bool bOkIfExists) return true; HKEY tmpKey; -#ifdef __WXWINCE__ DWORD disposition; - m_dwLastError = RegCreateKeyEx((HKEY) m_hRootKey, m_strKey.wx_str(), - 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.c_str(), &tmpKey); -#endif + if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't create registry key '%s'"), GetName().c_str()); @@ -534,7 +589,7 @@ bool wxRegKey::CopyValue(const wxString& szValue, bool wxRegKey::Rename(const wxString& szNewName) { - wxCHECK_MSG( !m_strKey.empty(), 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."), @@ -698,8 +753,25 @@ bool wxRegKey::DeleteSelf() // now delete this key itself Close(); - m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey.c_str()); // 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'"), @@ -791,7 +863,7 @@ bool wxRegKey::HasSubKey(const wxString& 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 wxString& szValue) const @@ -942,12 +1014,12 @@ bool wxRegKey::QueryValue(const wxString& szValue, #ifndef __WXWINCE__ if ( (dwType == REG_EXPAND_SZ) && !raw ) { - DWORD dwExpSize = ::ExpandEnvironmentStrings(strValue.c_str(), NULL, 0); + DWORD dwExpSize = ::ExpandEnvironmentStrings(strValue.t_str(), NULL, 0); bool ok = dwExpSize != 0; if ( ok ) { wxString strExpValue; - ok = ::ExpandEnvironmentStrings(strValue.c_str(), + ok = ::ExpandEnvironmentStrings(strValue.t_str(), wxStringBuffer(strExpValue, dwExpSize), dwExpSize ) != 0; @@ -956,7 +1028,7 @@ bool wxRegKey::QueryValue(const wxString& szValue, if ( !ok ) { - wxLogLastError(_T("ExpandEnvironmentStrings")); + wxLogLastError(wxT("ExpandEnvironmentStrings")); } } #endif @@ -985,7 +1057,7 @@ bool wxRegKey::SetValue(const wxString& szValue, const wxString& strValue) m_dwLastError = RegSetValueEx((HKEY) m_hKey, RegValueStr(szValue), (DWORD) RESERVED, REG_SZ, - (RegString)strValue.wx_str(), + (RegString)strValue.t_str(), (strValue.Len() + 1)*sizeof(wxChar)); if ( m_dwLastError == ERROR_SUCCESS ) return true; @@ -1161,9 +1233,9 @@ 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; @@ -1187,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; @@ -1233,7 +1305,7 @@ 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; @@ -1242,15 +1314,15 @@ wxString wxRegKey::FormatValue(const wxString& name) const { 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: @@ -1261,7 +1333,7 @@ wxString wxRegKey::FormatValue(const wxString& name) const if ( useHex ) rhs = FormatAsHex(value, Type_String); else - rhs += _T('"'); + rhs += wxT('"'); } break; @@ -1272,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; @@ -1364,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 ) { @@ -1398,7 +1470,9 @@ bool wxRegKey::DoExport(wxOutputStream& ostr) const // implementation of global private functions // ============================================================================ -bool KeyExists(WXHKEY hRootKey, const wxString& szKey) +bool KeyExists(WXHKEY hRootKey, + const wxString& szKey, + wxRegKey::WOW64ViewMode viewMode) { // don't close this key itself for the case of empty szKey! if ( szKey.empty() ) @@ -1408,9 +1482,10 @@ bool KeyExists(WXHKEY hRootKey, const wxString& szKey) if ( ::RegOpenKeyEx ( (HKEY)hRootKey, - szKey.c_str(), + 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 ) { @@ -1422,6 +1497,49 @@ bool KeyExists(WXHKEY hRootKey, const wxString& szKey) return false; } +long GetMSWViewFlags(wxRegKey::WOW64ViewMode viewMode) +{ + long samWOW64ViewMode = 0; + + 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; +} + +long GetMSWAccessFlags(wxRegKey::AccessMode mode, + wxRegKey::WOW64ViewMode viewMode) +{ + 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()); @@ -1444,7 +1562,7 @@ inline void RemoveTrailingSeparator(wxString& str) inline const wxChar *RegValueStr(const wxString& szValue) { - return szValue.empty() ? (const wxChar*)NULL : szValue.c_str(); + return szValue.empty() ? (const wxChar*)NULL : szValue.t_str(); } #endif // wxUSE_REGKEY