diff --git a/docs/changes.txt b/docs/changes.txt index 1797e310ff..4de5cd0cc1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -634,6 +634,7 @@ wxMSW: - Fix RegisterHotKey() with negative IDs (troelsk). - Fix event object type for wxEVT_SPINCTRL events. - Fix bug if wxToolBar tool was deleted from its own handler (Artur Wieczorek). +- Fix creating or modifying file associations under recent Windows versions. wxOSX: diff --git a/include/wx/platform.h b/include/wx/platform.h index eb4d4864c0..bb671f0158 100644 --- a/include/wx/platform.h +++ b/include/wx/platform.h @@ -310,7 +310,7 @@ */ #elif defined(__UNIX__) || defined(__unix) || defined(__unix__) || \ defined(____SVR4____) || defined(__LINUX__) || defined(__sgi) || \ - defined(__hpux) || defined(sun) || defined(__SUN__) || defined(_AIX) || \ + defined(__hpux) || defined(__sun) || defined(__SUN__) || defined(_AIX) || \ defined(__EMX__) || defined(__VMS) || defined(__BEOS__) || defined(__MACH__) # define __UNIX_LIKE__ diff --git a/src/msw/mimetype.cpp b/src/msw/mimetype.cpp index 84ff99912a..356102d866 100644 --- a/src/msw/mimetype.cpp +++ b/src/msw/mimetype.cpp @@ -66,6 +66,17 @@ class WXDLLIMPEXP_FWD_CORE wxIcon; // to open/print the file (the positional parameters are introduced by %1, // %2, ... in these strings, we change them to %s ourselves) +// Notice that HKCR can be used only when reading from the registry, when +// writing to it, we need to write to HKCU\Software\Classes instead as HKCR is +// a merged view of that location and HKLM\Software\Classes that we generally +// wouldn't have the write permissions to but writing to HKCR will try writing +// to the latter unless the key being written to already exists under the +// former, resulting in a "Permission denied" error without administrative +// permissions. So the right thing to do is to use HKCR when reading, to +// respect both per-user and machine-global associations, but only write under +// HKCU. +static const wxChar *CLASSES_ROOT_KEY = wxS("Software\\Classes\\"); + // although I don't know of any official documentation which mentions this // location, uses it, so it isn't likely to change static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\"); @@ -190,7 +201,7 @@ size_t wxFileTypeImpl::GetAllCommands(wxArrayString *verbs, bool wxFileTypeImpl::EnsureExtKeyExists() { - wxRegKey rkey(wxRegKey::HKCR, m_ext); + wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_ext); if ( !rkey.Exists() ) { if ( !rkey.Create() || !rkey.SetValue(wxEmptyString, m_strFileType) ) @@ -514,20 +525,6 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) return CreateFileType(wxEmptyString, ext); } -/* -wxFileType * -wxMimeTypesManagerImpl::GetOrAllocateFileTypeFromExtension(const wxString& ext) -{ - wxFileType *fileType = GetFileTypeFromExtension(ext); - if ( !fileType ) - { - fileType = CreateFileType(wxEmptyString, ext); - } - - return fileType; -} -*/ - // MIME type -> extension -> file type wxFileType * wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType) @@ -591,11 +588,11 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) extWithDot = wxT('.'); extWithDot += ext; - // start by setting the HKCR\\.ext entries + // start by setting the entries under ".ext" // default is filetype; content type is mimetype const wxString& filetypeOrig = ftInfo.GetShortDesc(); - wxRegKey key(wxRegKey::HKCR, extWithDot); + wxRegKey key(wxRegKey::HKCU, CLASSES_ROOT_KEY + extWithDot); if ( !key.Exists() ) { // create the mapping from the extension to the filetype @@ -643,7 +640,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) // create the MIME key wxString strKey = MIME_DATABASE_KEY; strKey << mimetype; - wxRegKey keyMIME(wxRegKey::HKCR, strKey); + wxRegKey keyMIME(wxRegKey::HKCU, CLASSES_ROOT_KEY + strKey); ok = keyMIME.Create(); if ( ok ) @@ -664,7 +661,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) extWithDot = wxT('.'); extWithDot += ext; - wxRegKey key2(wxRegKey::HKCR, extWithDot); + wxRegKey key2(wxRegKey::HKCU, CLASSES_ROOT_KEY + extWithDot); if ( !key2.Exists() ) key2.Create(); key2.SetValue(wxEmptyString, filetype); @@ -681,7 +678,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) // create the MIME key wxString strKey = MIME_DATABASE_KEY; strKey << mimetype2; - wxRegKey keyMIME(wxRegKey::HKCR, strKey); + wxRegKey keyMIME(wxRegKey::HKCU, CLASSES_ROOT_KEY + strKey); ok = keyMIME.Create(); if ( ok ) @@ -692,11 +689,11 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) } } - } // end of for loop; all extensions now point to HKCR\.ext\Default + } // end of for loop; all extensions now point to .ext\Default // create the filetype key itself (it will be empty for now, but // SetCommand(), SetDefaultIcon() &c will use it later) - wxRegKey keyFT(wxRegKey::HKCR, filetype); + wxRegKey keyFT(wxRegKey::HKCU, CLASSES_ROOT_KEY + filetype); keyFT.Create(); wxFileType *ft = CreateFileType(filetype, extWithDot); @@ -724,66 +721,14 @@ bool wxFileTypeImpl::SetCommand(const wxString& cmd, if ( !EnsureExtKeyExists() ) return false; - wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb)); -#if 0 - if ( rkey.Exists() && overwriteprompt ) - { -#if wxUSE_GUI - wxString old; - rkey.QueryValue(wxEmptyString, old); - if ( wxMessageBox - ( - wxString::Format( - _("Do you want to overwrite the command used to %s " - "files with extension \"%s\" ?\nCurrent value is \n%s, " - "\nNew value is \n%s %1"), // bug here FIX need %1 ?? - verb.c_str(), - m_ext.c_str(), - old.c_str(), - cmd.c_str()), - _("Confirm registry update"), - wxYES_NO | wxICON_QUESTION - ) != wxYES ) -#endif // wxUSE_GUI - { - // cancelled by user - return false; - } - } -#endif + wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + GetVerbPath(verb)); + // TODO: // 1. translate '%s' to '%1' instead of always adding it // 2. create DDEExec value if needed (undo GetCommand) return rkey.Create() && rkey.SetValue(wxEmptyString, cmd + wxT(" \"%1\"") ); } -/* // no longer used -bool wxFileTypeImpl::SetMimeType(const wxString& mimeTypeOrig) -{ - wxCHECK_MSG( !m_ext.empty(), false, wxT("SetMimeType() needs extension") ); - - if ( !EnsureExtKeyExists() ) - return false; - - // VZ: is this really useful? (FIXME) - wxString mimeType; - if ( !mimeTypeOrig ) - { - // make up a default value for it - wxString cmd; - wxFileName::SplitPath(GetCommand(wxT("open")), NULL, &cmd, NULL); - mimeType << wxT("application/x-") << cmd; - } - else - { - mimeType = mimeTypeOrig; - } - - wxRegKey rkey(wxRegKey::HKCR, m_ext); - return rkey.Create() && rkey.SetValue(wxT("Content Type"), mimeType); -} -*/ - bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index) { wxCHECK_MSG( !m_ext.empty(), false, wxT("SetDefaultIcon() needs extension") ); @@ -794,7 +739,8 @@ bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index) if ( !EnsureExtKeyExists() ) return false; - wxRegKey rkey(wxRegKey::HKCR, m_strFileType + wxT("\\DefaultIcon")); + wxRegKey rkey(wxRegKey::HKCU, + CLASSES_ROOT_KEY + m_strFileType + wxT("\\DefaultIcon")); return rkey.Create() && rkey.SetValue(wxEmptyString, @@ -809,7 +755,7 @@ bool wxFileTypeImpl::SetDescription (const wxString& desc) if ( !EnsureExtKeyExists() ) return false; - wxRegKey rkey(wxRegKey::HKCR, m_strFileType ); + wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_strFileType ); return rkey.Create() && rkey.SetValue(wxEmptyString, desc); @@ -831,16 +777,6 @@ bool wxFileTypeImpl::Unassociate() if ( !RemoveDescription() ) result = false; -/* - //this might hold other keys, eg some have CSLID keys - if ( result ) - { - // delete the root key - wxRegKey key(wxRegKey::HKCR, m_ext); - if ( key.Exists() ) - result = key.DeleteSelf(); - } -*/ return result; } @@ -854,7 +790,7 @@ bool wxFileTypeImpl::RemoveCommand(const wxString& verb) wxCHECK_MSG( !m_ext.empty() && !verb.empty(), false, wxT("RemoveCommand() needs an extension and a verb") ); - wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb)); + wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + GetVerbPath(verb)); // if the key already doesn't exist, it's a success return !rkey.Exists() || rkey.DeleteSelf(); @@ -864,7 +800,7 @@ bool wxFileTypeImpl::RemoveMimeType() { wxCHECK_MSG( !m_ext.empty(), false, wxT("RemoveMimeType() needs extension") ); - wxRegKey rkey(wxRegKey::HKCR, m_ext); + wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_ext); return !rkey.Exists() || rkey.DeleteSelf(); } @@ -873,7 +809,8 @@ bool wxFileTypeImpl::RemoveDefaultIcon() wxCHECK_MSG( !m_ext.empty(), false, wxT("RemoveDefaultIcon() needs extension") ); - wxRegKey rkey (wxRegKey::HKCR, m_strFileType + wxT("\\DefaultIcon")); + wxRegKey rkey (wxRegKey::HKCU, + CLASSES_ROOT_KEY + m_strFileType + wxT("\\DefaultIcon")); return !rkey.Exists() || rkey.DeleteSelf(); } @@ -882,7 +819,7 @@ bool wxFileTypeImpl::RemoveDescription() wxCHECK_MSG( !m_ext.empty(), false, wxT("RemoveDescription() needs extension") ); - wxRegKey rkey (wxRegKey::HKCR, m_strFileType ); + wxRegKey rkey (wxRegKey::HKCU, CLASSES_ROOT_KEY + m_strFileType ); return !rkey.Exists() || rkey.DeleteSelf(); } diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index d84b94f560..0042757296 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -384,9 +384,9 @@ const wxChar* wxGetHomeDir(wxString *pstr) // Cygwin returns unix type path but that does not work well static wxChar windowsPath[MAX_PATH]; #if CYGWIN_VERSION_DLL_MAJOR >= 1007 - cygwin_conv_path(CCP_POSIX_TO_WIN_W, strDir, windowsPath, MAX_PATH); + cygwin_conv_path(CCP_POSIX_TO_WIN_W, strDir.c_str(), windowsPath, MAX_PATH); #else - cygwin_conv_to_full_win32_path(strDir, windowsPath); + cygwin_conv_to_full_win32_path(strDir.c_str(), windowsPath); #endif strDir = windowsPath; #endif