X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9a83f860948059b0273b5cc6d9e43fadad3ebfca..779e28da630ef9fba6441fb0bab01cd538a7e7bb:/src/msw/registry.cpp?ds=sidebyside diff --git a/src/msw/registry.cpp b/src/msw/registry.cpp index dbfb079c8c..80903a6e4d 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.clear(); + 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) @@ -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) -#endif - // 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 + + 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 ) { @@ -387,7 +444,7 @@ bool wxRegKey::Open(AccessMode mode) (HKEY) m_hRootKey, 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.t_str(), &tmpKey); -#endif + if ( m_dwLastError != ERROR_SUCCESS ) { wxLogSysError(m_dwLastError, _("Can't create registry key '%s'"), GetName().c_str()); @@ -698,8 +753,25 @@ bool wxRegKey::DeleteSelf() // now delete this key itself Close(); - m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey.t_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 @@ -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)static_cast(strValue.t_str()), (strValue.Len() + 1)*sizeof(wxChar)); if ( m_dwLastError == ERROR_SUCCESS ) return true; @@ -1163,7 +1235,7 @@ bool wxRegKey::Export(const wxString& filename) const wxFFileOutputStream ostr(filename, wxT("w")); - return ostr.Ok() && Export(ostr); + return ostr.IsOk() && Export(ostr); #else wxUnusedVar(filename); return false; @@ -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() ) @@ -1410,7 +1484,8 @@ bool KeyExists(WXHKEY hRootKey, const wxString& szKey) (HKEY)hRootKey, 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());